terminalhire 0.17.1 → 0.17.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.
- package/dist/bin/jpi-bounties.js +192 -68
- package/dist/bin/jpi-chat-read.js +43 -19
- package/dist/bin/jpi-chat.js +43 -19
- package/dist/bin/jpi-claim.js +734 -39
- package/dist/bin/jpi-contribute.js +51 -21
- package/dist/bin/jpi-devs.js +176 -55
- package/dist/bin/jpi-dispatch.js +431 -108
- package/dist/bin/jpi-inbox.js +43 -19
- package/dist/bin/jpi-intro.js +43 -19
- package/dist/bin/jpi-jobs.js +176 -55
- package/dist/bin/jpi-learn.js +43 -19
- package/dist/bin/jpi-link.js +55 -1
- package/dist/bin/jpi-login.js +176 -55
- package/dist/bin/jpi-profile.js +43 -19
- package/dist/bin/jpi-project.js +174 -53
- package/dist/bin/jpi-refresh.js +176 -55
- package/dist/bin/jpi-save.js +43 -19
- package/dist/bin/jpi-spinner.js +18 -3
- package/dist/bin/jpi-sync.js +43 -19
- package/dist/bin/jpi-trajectory.js +120 -78
- package/dist/bin/spinner.js +20 -4
- package/dist/src/chat-client.js +20 -5
- package/dist/src/chat-keystore.js +20 -5
- package/dist/src/claims.js +9 -1
- package/dist/src/github-auth.js +2 -2
- package/dist/src/intro.js +43 -19
- package/dist/src/link.js +10 -0
- package/dist/src/profile.js +20 -5
- package/dist/src/repo-policy.js +77 -0
- package/dist/src/signal.js +18 -3
- package/dist/src/trajectory.js +87 -43
- package/package.json +1 -1
package/dist/bin/jpi-bounties.js
CHANGED
|
@@ -644,15 +644,90 @@ var init_vocabulary = __esm({
|
|
|
644
644
|
}
|
|
645
645
|
});
|
|
646
646
|
|
|
647
|
+
// ../../packages/core/src/feeds/bounty-gate.ts
|
|
648
|
+
function isDenylistedRepo(fullName) {
|
|
649
|
+
return DENYLIST_LC.has(fullName.toLowerCase());
|
|
650
|
+
}
|
|
651
|
+
function isAiBanRepo(fullName) {
|
|
652
|
+
const lc = fullName.toLowerCase();
|
|
653
|
+
const owner = lc.split("/")[0];
|
|
654
|
+
return AI_BAN_LC.has(lc) || AI_BAN_LC.has(owner);
|
|
655
|
+
}
|
|
656
|
+
function passesAntiFarm(amountUSD, stargazers) {
|
|
657
|
+
return !(amountUSD > HIGH_VALUE_USD && stargazers < HIGH_VALUE_MIN_STARS);
|
|
658
|
+
}
|
|
659
|
+
function ageDays(createdAtIso) {
|
|
660
|
+
const created = Date.parse(createdAtIso);
|
|
661
|
+
if (!Number.isFinite(created)) return 0;
|
|
662
|
+
return (Date.now() - created) / (1e3 * 60 * 60 * 24);
|
|
663
|
+
}
|
|
664
|
+
function passesMaturityGate(repo) {
|
|
665
|
+
if (isDenylistedRepo(repo.fullName)) return false;
|
|
666
|
+
if (isAiBanRepo(repo.fullName)) return false;
|
|
667
|
+
if (repo.archived || repo.disabled) return false;
|
|
668
|
+
if (repo.stargazers < MIN_REPO_STARS) return false;
|
|
669
|
+
if (ageDays(repo.createdAt) < MIN_REPO_AGE_DAYS) return false;
|
|
670
|
+
return true;
|
|
671
|
+
}
|
|
672
|
+
var DEFAULT_BOUNTY_REPOS, BOUNTY_REPO_DENYLIST, DENYLIST_LC, AI_BAN_DENYLIST, AI_BAN_LC, MAX_BOUNTIES_PER_REPO, MAX_BOUNTIES_PER_DISCOVERED_REPO, MIN_REPO_STARS, HIGH_VALUE_USD, HIGH_VALUE_MIN_STARS, MIN_REPO_AGE_DAYS;
|
|
673
|
+
var init_bounty_gate = __esm({
|
|
674
|
+
"../../packages/core/src/feeds/bounty-gate.ts"() {
|
|
675
|
+
"use strict";
|
|
676
|
+
DEFAULT_BOUNTY_REPOS = [
|
|
677
|
+
"tenstorrent/tt-metal",
|
|
678
|
+
"sequelize/sequelize",
|
|
679
|
+
"commaai/opendbc",
|
|
680
|
+
"aragon/hack",
|
|
681
|
+
"spacemeshos/app",
|
|
682
|
+
"archestra-ai/archestra",
|
|
683
|
+
"ucfopen/Obojobo",
|
|
684
|
+
"moorcheh-ai/memanto",
|
|
685
|
+
"PrismarineJS/mineflayer"
|
|
686
|
+
];
|
|
687
|
+
BOUNTY_REPO_DENYLIST = [
|
|
688
|
+
"SecureBananaLabs/bug-bounty",
|
|
689
|
+
// Meta-farm: a bounty PLATFORM whose own issues are an assignment-gated
|
|
690
|
+
// contributor queue ("please assign me, my chief") — an unsolicited PR won't
|
|
691
|
+
// merge, so it's not a real claimable bounty. Not structurally derivable from
|
|
692
|
+
// any fetched field, so it's a manual entry (also dropped from the allowlist).
|
|
693
|
+
"boundlessfi/boundless"
|
|
694
|
+
];
|
|
695
|
+
DENYLIST_LC = new Set(BOUNTY_REPO_DENYLIST.map((r) => r.toLowerCase()));
|
|
696
|
+
AI_BAN_DENYLIST = [
|
|
697
|
+
// Gentoo Council voted 6-0 (2024-04-14) to ban AI/ML-generated contributions
|
|
698
|
+
// project-wide. https://wiki.gentoo.org/wiki/Project:Council/AI_policy
|
|
699
|
+
"gentoo",
|
|
700
|
+
// NetBSD Commit Guidelines: code generated by an LLM/similar technology is
|
|
701
|
+
// "presumed to be tainted code, and must not be committed without prior
|
|
702
|
+
// written approval by core". https://www.netbsd.org/developers/commit-guidelines.html
|
|
703
|
+
"NetBSD"
|
|
704
|
+
// NOT listed (checked, deliberately excluded): QEMU's blanket AI-contribution
|
|
705
|
+
// ban is IN FLUX as of 2026-05 — a patch replacing it with a disclosure-based
|
|
706
|
+
// policy ("AI-used-for:" tag) was posted to qemu-devel and appears to have
|
|
707
|
+
// developer buy-in, so it is no longer a clean/current ban to key a hard
|
|
708
|
+
// supply-side drop on. https://www.theregister.com/ai-and-ml/2026/05/29/qemu-mulls-relaxing-ai-contribution-ban/
|
|
709
|
+
];
|
|
710
|
+
AI_BAN_LC = new Set(AI_BAN_DENYLIST.map((g) => g.toLowerCase()));
|
|
711
|
+
MAX_BOUNTIES_PER_REPO = 10;
|
|
712
|
+
MAX_BOUNTIES_PER_DISCOVERED_REPO = 3;
|
|
713
|
+
MIN_REPO_STARS = 5;
|
|
714
|
+
HIGH_VALUE_USD = 500;
|
|
715
|
+
HIGH_VALUE_MIN_STARS = 50;
|
|
716
|
+
MIN_REPO_AGE_DAYS = 30;
|
|
717
|
+
}
|
|
718
|
+
});
|
|
719
|
+
|
|
647
720
|
// ../../packages/core/src/feeds/contribution-gate.ts
|
|
648
721
|
function passesContributionGate(input) {
|
|
649
722
|
if (input.contributors === void 0) return false;
|
|
723
|
+
if (isAiBanRepo(input.fullName)) return false;
|
|
650
724
|
return input.stars >= MIN_STARS && input.contributors >= MIN_CONTRIBUTORS && !TRIVIAL_PR_TITLE.test(input.title) && !input.archived && !input.fork;
|
|
651
725
|
}
|
|
652
726
|
var MIN_STARS, MIN_CONTRIBUTORS, TRIVIAL_PR_TITLE;
|
|
653
727
|
var init_contribution_gate = __esm({
|
|
654
728
|
"../../packages/core/src/feeds/contribution-gate.ts"() {
|
|
655
729
|
"use strict";
|
|
730
|
+
init_bounty_gate();
|
|
656
731
|
MIN_STARS = 50;
|
|
657
732
|
MIN_CONTRIBUTORS = 10;
|
|
658
733
|
TRIVIAL_PR_TITLE = /^\s*(fix\s+typo|typo\b|update\s+readme|readme\b|docs?:|docs?\(|chore:|chore\(|style:|ci:|build:|bump\b|update\s+dependenc)/i;
|
|
@@ -1710,58 +1785,6 @@ var init_hn = __esm({
|
|
|
1710
1785
|
}
|
|
1711
1786
|
});
|
|
1712
1787
|
|
|
1713
|
-
// ../../packages/core/src/feeds/bounty-gate.ts
|
|
1714
|
-
function isDenylistedRepo(fullName) {
|
|
1715
|
-
return DENYLIST_LC.has(fullName.toLowerCase());
|
|
1716
|
-
}
|
|
1717
|
-
function passesAntiFarm(amountUSD, stargazers) {
|
|
1718
|
-
return !(amountUSD > HIGH_VALUE_USD && stargazers < HIGH_VALUE_MIN_STARS);
|
|
1719
|
-
}
|
|
1720
|
-
function ageDays(createdAtIso) {
|
|
1721
|
-
const created = Date.parse(createdAtIso);
|
|
1722
|
-
if (!Number.isFinite(created)) return 0;
|
|
1723
|
-
return (Date.now() - created) / (1e3 * 60 * 60 * 24);
|
|
1724
|
-
}
|
|
1725
|
-
function passesMaturityGate(repo) {
|
|
1726
|
-
if (isDenylistedRepo(repo.fullName)) return false;
|
|
1727
|
-
if (repo.archived || repo.disabled) return false;
|
|
1728
|
-
if (repo.stargazers < MIN_REPO_STARS) return false;
|
|
1729
|
-
if (ageDays(repo.createdAt) < MIN_REPO_AGE_DAYS) return false;
|
|
1730
|
-
return true;
|
|
1731
|
-
}
|
|
1732
|
-
var DEFAULT_BOUNTY_REPOS, BOUNTY_REPO_DENYLIST, DENYLIST_LC, MAX_BOUNTIES_PER_REPO, MAX_BOUNTIES_PER_DISCOVERED_REPO, MIN_REPO_STARS, HIGH_VALUE_USD, HIGH_VALUE_MIN_STARS, MIN_REPO_AGE_DAYS;
|
|
1733
|
-
var init_bounty_gate = __esm({
|
|
1734
|
-
"../../packages/core/src/feeds/bounty-gate.ts"() {
|
|
1735
|
-
"use strict";
|
|
1736
|
-
DEFAULT_BOUNTY_REPOS = [
|
|
1737
|
-
"tenstorrent/tt-metal",
|
|
1738
|
-
"sequelize/sequelize",
|
|
1739
|
-
"commaai/opendbc",
|
|
1740
|
-
"aragon/hack",
|
|
1741
|
-
"spacemeshos/app",
|
|
1742
|
-
"archestra-ai/archestra",
|
|
1743
|
-
"ucfopen/Obojobo",
|
|
1744
|
-
"moorcheh-ai/memanto",
|
|
1745
|
-
"PrismarineJS/mineflayer"
|
|
1746
|
-
];
|
|
1747
|
-
BOUNTY_REPO_DENYLIST = [
|
|
1748
|
-
"SecureBananaLabs/bug-bounty",
|
|
1749
|
-
// Meta-farm: a bounty PLATFORM whose own issues are an assignment-gated
|
|
1750
|
-
// contributor queue ("please assign me, my chief") — an unsolicited PR won't
|
|
1751
|
-
// merge, so it's not a real claimable bounty. Not structurally derivable from
|
|
1752
|
-
// any fetched field, so it's a manual entry (also dropped from the allowlist).
|
|
1753
|
-
"boundlessfi/boundless"
|
|
1754
|
-
];
|
|
1755
|
-
DENYLIST_LC = new Set(BOUNTY_REPO_DENYLIST.map((r) => r.toLowerCase()));
|
|
1756
|
-
MAX_BOUNTIES_PER_REPO = 10;
|
|
1757
|
-
MAX_BOUNTIES_PER_DISCOVERED_REPO = 3;
|
|
1758
|
-
MIN_REPO_STARS = 5;
|
|
1759
|
-
HIGH_VALUE_USD = 500;
|
|
1760
|
-
HIGH_VALUE_MIN_STARS = 50;
|
|
1761
|
-
MIN_REPO_AGE_DAYS = 30;
|
|
1762
|
-
}
|
|
1763
|
-
});
|
|
1764
|
-
|
|
1765
1788
|
// ../../packages/core/src/concurrency.ts
|
|
1766
1789
|
async function mapWithConcurrency(items, limit, fn) {
|
|
1767
1790
|
const results = new Array(items.length);
|
|
@@ -2413,6 +2436,7 @@ async function aggregateBounties(opts) {
|
|
|
2413
2436
|
const repo = j.bounty?.repoFullName?.toLowerCase();
|
|
2414
2437
|
if (repo) {
|
|
2415
2438
|
if (isDenylistedRepo(repo)) continue;
|
|
2439
|
+
if (isAiBanRepo(repo)) continue;
|
|
2416
2440
|
const titleKey = `${repo} ${normalizeBountyTitle(j.title)}`;
|
|
2417
2441
|
if (seenRepoTitles.has(titleKey)) continue;
|
|
2418
2442
|
const cap = allowlist.has(repo) ? MAX_BOUNTIES_PER_REPO : MAX_BOUNTIES_PER_DISCOVERED_REPO;
|
|
@@ -2750,6 +2774,7 @@ async function aggregateContributions(opts = {}) {
|
|
|
2750
2774
|
const title = decodeEntities(issue.title).trim();
|
|
2751
2775
|
const contributors = await repoContribCount(fullName);
|
|
2752
2776
|
if (!passesContributionGate({
|
|
2777
|
+
fullName,
|
|
2753
2778
|
stars: repo.stargazers_count,
|
|
2754
2779
|
contributors,
|
|
2755
2780
|
title,
|
|
@@ -2819,21 +2844,21 @@ var init_contributions = __esm({
|
|
|
2819
2844
|
});
|
|
2820
2845
|
|
|
2821
2846
|
// ../../packages/core/src/partners.ts
|
|
2822
|
-
import { readFileSync
|
|
2823
|
-
import { join
|
|
2847
|
+
import { readFileSync } from "fs";
|
|
2848
|
+
import { join } from "path";
|
|
2824
2849
|
import { fileURLToPath } from "url";
|
|
2825
2850
|
function resolveDataPath() {
|
|
2826
2851
|
try {
|
|
2827
2852
|
const dir = fileURLToPath(new URL("../../../data", import.meta.url));
|
|
2828
|
-
return
|
|
2853
|
+
return join(dir, "partner-roles.json");
|
|
2829
2854
|
} catch {
|
|
2830
|
-
return
|
|
2855
|
+
return join(process.cwd(), "data", "partner-roles.json");
|
|
2831
2856
|
}
|
|
2832
2857
|
}
|
|
2833
2858
|
function loadPartnerRoles() {
|
|
2834
2859
|
const filePath = resolveDataPath();
|
|
2835
2860
|
try {
|
|
2836
|
-
const raw =
|
|
2861
|
+
const raw = readFileSync(filePath, "utf-8");
|
|
2837
2862
|
const parsed = JSON.parse(raw);
|
|
2838
2863
|
if (!Array.isArray(parsed)) {
|
|
2839
2864
|
console.warn("[partners] partner-roles.json is not an array \u2014 skipping");
|
|
@@ -6345,27 +6370,113 @@ var init_legible = __esm({
|
|
|
6345
6370
|
}
|
|
6346
6371
|
});
|
|
6347
6372
|
|
|
6373
|
+
// ../../packages/core/src/credential/legible-trajectory.ts
|
|
6374
|
+
function signalLabel(signal) {
|
|
6375
|
+
if (signal.startsWith("lang:")) {
|
|
6376
|
+
const token = signal.slice("lang:".length);
|
|
6377
|
+
return LANG_LABELS[token] ?? token.toUpperCase();
|
|
6378
|
+
}
|
|
6379
|
+
if (CAP_LABELS[signal]) return CAP_LABELS[signal];
|
|
6380
|
+
if (signal.startsWith("cap:")) return signal.slice("cap:".length).replace(/-/g, " ");
|
|
6381
|
+
return signal;
|
|
6382
|
+
}
|
|
6383
|
+
function joinLabels(labels) {
|
|
6384
|
+
if (labels.length === 0) return "";
|
|
6385
|
+
if (labels.length === 1) return labels[0];
|
|
6386
|
+
return `${labels.slice(0, -1).join(", ")} and ${labels[labels.length - 1]}`;
|
|
6387
|
+
}
|
|
6388
|
+
function mentionable(entries) {
|
|
6389
|
+
return entries.filter((e) => Math.abs(e.delta) >= MENTION_DELTA).slice(0, MAX_NAMED).map((e) => signalLabel(e.signal));
|
|
6390
|
+
}
|
|
6391
|
+
function displayableDrift(entries) {
|
|
6392
|
+
return entries.filter((e) => Math.abs(e.delta) >= DISPLAY_DELTA_FLOOR);
|
|
6393
|
+
}
|
|
6394
|
+
function deriveTrajectoryNarrative(score) {
|
|
6395
|
+
const risingLabels = mentionable(score.headline.rising);
|
|
6396
|
+
const fallingLabels = mentionable(score.headline.falling);
|
|
6397
|
+
let momentum;
|
|
6398
|
+
if (risingLabels.length === 0 && fallingLabels.length === 0) {
|
|
6399
|
+
momentum = "Steady focus \u2014 no major shifts recently.";
|
|
6400
|
+
} else {
|
|
6401
|
+
const parts = [];
|
|
6402
|
+
if (risingLabels.length > 0) parts.push(`Trending toward ${joinLabels(risingLabels)}`);
|
|
6403
|
+
if (fallingLabels.length > 0) {
|
|
6404
|
+
parts.push(
|
|
6405
|
+
risingLabels.length > 0 ? `shifting away from ${joinLabels(fallingLabels)}` : `Shifting away from ${joinLabels(fallingLabels)}`
|
|
6406
|
+
);
|
|
6407
|
+
}
|
|
6408
|
+
momentum = `${parts.join(", ")}.`;
|
|
6409
|
+
}
|
|
6410
|
+
const liveLangs = score.liveStack.filter((s) => s.startsWith("lang:")).map(signalLabel);
|
|
6411
|
+
const liveCaps = score.liveStack.filter((s) => !s.startsWith("lang:")).map(signalLabel);
|
|
6412
|
+
const focusParts = [];
|
|
6413
|
+
if (liveLangs.length > 0) focusParts.push(`Ships in ${joinLabels(liveLangs)}`);
|
|
6414
|
+
if (liveCaps.length > 0) {
|
|
6415
|
+
const verb = liveLangs.length > 0 ? "works with" : "Works with";
|
|
6416
|
+
focusParts.push(`${verb} ${joinLabels(liveCaps)}`);
|
|
6417
|
+
}
|
|
6418
|
+
const focus = focusParts.length > 0 ? `${focusParts.join(" \xB7 ")}.` : "";
|
|
6419
|
+
return { momentum, focus, risingLabels, fallingLabels };
|
|
6420
|
+
}
|
|
6421
|
+
var LANG_LABELS, CAP_LABELS, MENTION_DELTA, DISPLAY_DELTA_FLOOR, MAX_NAMED;
|
|
6422
|
+
var init_legible_trajectory = __esm({
|
|
6423
|
+
"../../packages/core/src/credential/legible-trajectory.ts"() {
|
|
6424
|
+
"use strict";
|
|
6425
|
+
LANG_LABELS = {
|
|
6426
|
+
ts: "TypeScript",
|
|
6427
|
+
js: "JavaScript",
|
|
6428
|
+
py: "Python",
|
|
6429
|
+
rs: "Rust",
|
|
6430
|
+
go: "Go",
|
|
6431
|
+
rb: "Ruby",
|
|
6432
|
+
java: "Java",
|
|
6433
|
+
kt: "Kotlin",
|
|
6434
|
+
sql: "SQL",
|
|
6435
|
+
md: "Documentation"
|
|
6436
|
+
};
|
|
6437
|
+
CAP_LABELS = {
|
|
6438
|
+
"cap:ui-automation": "UI automation",
|
|
6439
|
+
"cap:deploys": "Deployment",
|
|
6440
|
+
"cap:project-mgmt": "Project tracking",
|
|
6441
|
+
"cap:product-research": "Product research",
|
|
6442
|
+
"cap:design": "Design",
|
|
6443
|
+
"cap:3d-modeling": "3D modeling",
|
|
6444
|
+
"cap:workflow-automation": "Workflow automation",
|
|
6445
|
+
"cap:agentic-workflow": "Agent orchestration",
|
|
6446
|
+
"mcp:custom": "Private integrations"
|
|
6447
|
+
};
|
|
6448
|
+
MENTION_DELTA = 0.05;
|
|
6449
|
+
DISPLAY_DELTA_FLOOR = 5e-4;
|
|
6450
|
+
MAX_NAMED = 3;
|
|
6451
|
+
}
|
|
6452
|
+
});
|
|
6453
|
+
|
|
6348
6454
|
// ../../packages/core/src/short-token.ts
|
|
6349
6455
|
import { createHash as createHash2 } from "crypto";
|
|
6350
|
-
function
|
|
6456
|
+
function opportunityShortToken(id) {
|
|
6351
6457
|
return createHash2("sha256").update(id, "utf8").digest("base64url").slice(0, 8);
|
|
6352
6458
|
}
|
|
6459
|
+
var contributeShortToken;
|
|
6353
6460
|
var init_short_token = __esm({
|
|
6354
6461
|
"../../packages/core/src/short-token.ts"() {
|
|
6355
6462
|
"use strict";
|
|
6463
|
+
contributeShortToken = opportunityShortToken;
|
|
6356
6464
|
}
|
|
6357
6465
|
});
|
|
6358
6466
|
|
|
6359
6467
|
// ../../packages/core/src/index.ts
|
|
6360
6468
|
var src_exports = {};
|
|
6361
6469
|
__export(src_exports, {
|
|
6470
|
+
AI_BAN_DENYLIST: () => AI_BAN_DENYLIST,
|
|
6362
6471
|
ASHBY_SLUGS_BY_TIER: () => ASHBY_SLUGS_BY_TIER,
|
|
6472
|
+
CAP_LABELS: () => CAP_LABELS,
|
|
6363
6473
|
DECAY_FLOOR: () => DECAY_FLOOR,
|
|
6364
6474
|
DEFAULT_ASHBY_SLUGS: () => DEFAULT_ASHBY_SLUGS,
|
|
6365
6475
|
DEFAULT_BOUNTY_REPOS: () => DEFAULT_BOUNTY_REPOS,
|
|
6366
6476
|
DEFAULT_GREENHOUSE_SLUGS: () => DEFAULT_GREENHOUSE_SLUGS,
|
|
6367
6477
|
DEFAULT_LEVER_SLUGS: () => DEFAULT_LEVER_SLUGS,
|
|
6368
6478
|
DEFAULT_WORKABLE_SLUGS: () => DEFAULT_WORKABLE_SLUGS,
|
|
6479
|
+
DISPLAY_DELTA_FLOOR: () => DISPLAY_DELTA_FLOOR,
|
|
6369
6480
|
EXAMPLE_BUYER: () => EXAMPLE_BUYER,
|
|
6370
6481
|
FEEDS: () => FEEDS,
|
|
6371
6482
|
GRAPH: () => GRAPH,
|
|
@@ -6374,7 +6485,9 @@ __export(src_exports, {
|
|
|
6374
6485
|
INTRO_ACCEPTED_TTL_MS: () => INTRO_ACCEPTED_TTL_MS,
|
|
6375
6486
|
INTRO_ALLOWED_FIELDS: () => INTRO_ALLOWED_FIELDS,
|
|
6376
6487
|
INTRO_PENDING_TTL_MS: () => INTRO_PENDING_TTL_MS,
|
|
6488
|
+
LANG_LABELS: () => LANG_LABELS,
|
|
6377
6489
|
LEVER_SLUGS_BY_TIER: () => LEVER_SLUGS_BY_TIER,
|
|
6490
|
+
MENTION_DELTA: () => MENTION_DELTA,
|
|
6378
6491
|
MIN_CONTRIBUTORS: () => MIN_CONTRIBUTORS,
|
|
6379
6492
|
MIN_STARS: () => MIN_STARS,
|
|
6380
6493
|
STRONG_MATCH_THRESHOLD: () => STRONG_MATCH_THRESHOLD,
|
|
@@ -6406,6 +6519,8 @@ __export(src_exports, {
|
|
|
6406
6519
|
deriveLegibleProfile: () => deriveLegibleProfile,
|
|
6407
6520
|
deriveResumeTrend: () => deriveResumeTrend,
|
|
6408
6521
|
deriveSharedKey: () => deriveSharedKey,
|
|
6522
|
+
deriveTrajectoryNarrative: () => deriveTrajectoryNarrative,
|
|
6523
|
+
displayableDrift: () => displayableDrift,
|
|
6409
6524
|
encryptMessage: () => encryptMessage,
|
|
6410
6525
|
expandWeighted: () => expandWeighted,
|
|
6411
6526
|
extractSkillTags: () => extractSkillTags,
|
|
@@ -6425,15 +6540,19 @@ __export(src_exports, {
|
|
|
6425
6540
|
introActorRole: () => introActorRole,
|
|
6426
6541
|
introRateLimitCheck: () => introRateLimitCheck,
|
|
6427
6542
|
introRetentionAction: () => introRetentionAction,
|
|
6543
|
+
isAiBanRepo: () => isAiBanRepo,
|
|
6428
6544
|
isBounty: () => isBounty,
|
|
6429
6545
|
isContribution: () => isContribution,
|
|
6430
6546
|
isOverIntroLimit: () => isOverIntroLimit,
|
|
6547
|
+
joinLabels: () => joinLabels,
|
|
6548
|
+
labelFor: () => labelFor,
|
|
6431
6549
|
lever: () => lever,
|
|
6432
6550
|
loadPartnerRoles: () => loadPartnerRoles,
|
|
6433
6551
|
looksLikeEngRole: () => looksLikeEngRole,
|
|
6434
6552
|
match: () => match,
|
|
6435
6553
|
normalize: () => normalize,
|
|
6436
6554
|
opire: () => opire,
|
|
6555
|
+
opportunityShortToken: () => opportunityShortToken,
|
|
6437
6556
|
pageMatches: () => pageMatches,
|
|
6438
6557
|
passesContributionGate: () => passesContributionGate,
|
|
6439
6558
|
passesMaturityGate: () => passesMaturityGate,
|
|
@@ -6445,6 +6564,7 @@ __export(src_exports, {
|
|
|
6445
6564
|
safetyNumber: () => safetyNumber,
|
|
6446
6565
|
sameLogin: () => sameLogin,
|
|
6447
6566
|
setStatus: () => setStatus,
|
|
6567
|
+
signalLabel: () => signalLabel,
|
|
6448
6568
|
tokenize: () => tokenize,
|
|
6449
6569
|
validateGraph: () => validateGraph,
|
|
6450
6570
|
validateIntroPayload: () => validateIntroPayload,
|
|
@@ -6467,6 +6587,7 @@ var init_src = __esm({
|
|
|
6467
6587
|
init_chatCrypto();
|
|
6468
6588
|
init_job_status();
|
|
6469
6589
|
init_legible();
|
|
6590
|
+
init_legible_trajectory();
|
|
6470
6591
|
init_short_token();
|
|
6471
6592
|
}
|
|
6472
6593
|
});
|
|
@@ -6479,9 +6600,9 @@ var init_keytar = __esm({
|
|
|
6479
6600
|
}
|
|
6480
6601
|
});
|
|
6481
6602
|
|
|
6482
|
-
// node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/3ffac25b-ca95-4a86-9e17-a4cf326551de/scratchpad/
|
|
6603
|
+
// node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/3ffac25b-ca95-4a86-9e17-a4cf326551de/scratchpad/rel2/node_modules/keytar/build/Release/keytar.node
|
|
6483
6604
|
var require_keytar = __commonJS({
|
|
6484
|
-
"node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/3ffac25b-ca95-4a86-9e17-a4cf326551de/scratchpad/
|
|
6605
|
+
"node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/3ffac25b-ca95-4a86-9e17-a4cf326551de/scratchpad/rel2/node_modules/keytar/build/Release/keytar.node"(exports, module) {
|
|
6485
6606
|
"use strict";
|
|
6486
6607
|
init_keytar();
|
|
6487
6608
|
try {
|
|
@@ -6771,22 +6892,23 @@ var init_profile = __esm({
|
|
|
6771
6892
|
});
|
|
6772
6893
|
|
|
6773
6894
|
// bin/jpi-bounties.js
|
|
6895
|
+
init_src();
|
|
6774
6896
|
import { readFileSync as readFileSync4 } from "fs";
|
|
6775
6897
|
import { join as join4 } from "path";
|
|
6776
6898
|
import { homedir as homedir3 } from "os";
|
|
6777
6899
|
import { createInterface } from "readline";
|
|
6778
6900
|
|
|
6779
6901
|
// bin/cache-store.js
|
|
6780
|
-
import { readFileSync, writeFileSync, mkdirSync, renameSync } from "fs";
|
|
6781
|
-
import { join } from "path";
|
|
6902
|
+
import { readFileSync as readFileSync2, writeFileSync, mkdirSync, renameSync } from "fs";
|
|
6903
|
+
import { join as join2 } from "path";
|
|
6782
6904
|
import { homedir } from "os";
|
|
6783
|
-
var TERMINALHIRE_DIR = process.env.TERMINALHIRE_DIR ||
|
|
6784
|
-
var INDEX_CACHE_FILE =
|
|
6785
|
-
var
|
|
6905
|
+
var TERMINALHIRE_DIR = process.env.TERMINALHIRE_DIR || join2(homedir(), ".terminalhire");
|
|
6906
|
+
var INDEX_CACHE_FILE = join2(TERMINALHIRE_DIR, "index-cache.json");
|
|
6907
|
+
var SCHEMA_VERSION2 = 1;
|
|
6786
6908
|
var tmpCounter = 0;
|
|
6787
6909
|
function readCacheEntry() {
|
|
6788
6910
|
try {
|
|
6789
|
-
return JSON.parse(
|
|
6911
|
+
return JSON.parse(readFileSync2(INDEX_CACHE_FILE, "utf8"));
|
|
6790
6912
|
} catch {
|
|
6791
6913
|
return null;
|
|
6792
6914
|
}
|
|
@@ -6797,7 +6919,7 @@ function updateIndexCache(patch) {
|
|
|
6797
6919
|
const entry = {
|
|
6798
6920
|
...existing,
|
|
6799
6921
|
...patch,
|
|
6800
|
-
schemaVersion:
|
|
6922
|
+
schemaVersion: SCHEMA_VERSION2,
|
|
6801
6923
|
ts: Date.now()
|
|
6802
6924
|
};
|
|
6803
6925
|
const tmp = `${INDEX_CACHE_FILE}.${process.pid}.${tmpCounter++}.tmp`;
|
|
@@ -6865,13 +6987,15 @@ function printBounty(i, job, score, reason, matchedTags) {
|
|
|
6865
6987
|
const scoreStr = score > 0 ? ` \xB7 match ${Math.round(score * 100)}%` : "";
|
|
6866
6988
|
const prs = b.competingOpenPRs;
|
|
6867
6989
|
const contend = prs != null && prs > 0 ? ` \xB7 \u26A0 ${prs} PR${prs === 1 ? "" : "s"} in flight` : "";
|
|
6990
|
+
const ref = opportunityShortToken(job.id);
|
|
6868
6991
|
console.log(`
|
|
6869
|
-
${i + 1}. ${linkTitle(job.title, job.url)}`);
|
|
6992
|
+
${i + 1}. ${linkTitle(job.title, job.url)} [${ref}]`);
|
|
6870
6993
|
console.log(` ${formatAmount(b)}${effort} \xB7 ${b.repoFullName ?? job.company}${stars}${scoreStr}${contend}`);
|
|
6871
6994
|
if (reason) console.log(` ${reason}`);
|
|
6872
6995
|
if (matchedTags && matchedTags.length) console.log(` Tags matched: ${matchedTags.slice(0, 5).join(", ")}`);
|
|
6873
6996
|
console.log(` id: ${job.id}`);
|
|
6874
6997
|
console.log(` Claim: ${b.claimUrl ?? job.url}`);
|
|
6998
|
+
console.log(` \u2192 terminalhire claim ${ref}`);
|
|
6875
6999
|
}
|
|
6876
7000
|
async function run() {
|
|
6877
7001
|
try {
|
|
@@ -422,10 +422,43 @@ var init_vocabulary = __esm({
|
|
|
422
422
|
}
|
|
423
423
|
});
|
|
424
424
|
|
|
425
|
+
// ../../packages/core/src/feeds/bounty-gate.ts
|
|
426
|
+
var BOUNTY_REPO_DENYLIST, DENYLIST_LC, AI_BAN_DENYLIST, AI_BAN_LC;
|
|
427
|
+
var init_bounty_gate = __esm({
|
|
428
|
+
"../../packages/core/src/feeds/bounty-gate.ts"() {
|
|
429
|
+
"use strict";
|
|
430
|
+
BOUNTY_REPO_DENYLIST = [
|
|
431
|
+
"SecureBananaLabs/bug-bounty",
|
|
432
|
+
// Meta-farm: a bounty PLATFORM whose own issues are an assignment-gated
|
|
433
|
+
// contributor queue ("please assign me, my chief") — an unsolicited PR won't
|
|
434
|
+
// merge, so it's not a real claimable bounty. Not structurally derivable from
|
|
435
|
+
// any fetched field, so it's a manual entry (also dropped from the allowlist).
|
|
436
|
+
"boundlessfi/boundless"
|
|
437
|
+
];
|
|
438
|
+
DENYLIST_LC = new Set(BOUNTY_REPO_DENYLIST.map((r) => r.toLowerCase()));
|
|
439
|
+
AI_BAN_DENYLIST = [
|
|
440
|
+
// Gentoo Council voted 6-0 (2024-04-14) to ban AI/ML-generated contributions
|
|
441
|
+
// project-wide. https://wiki.gentoo.org/wiki/Project:Council/AI_policy
|
|
442
|
+
"gentoo",
|
|
443
|
+
// NetBSD Commit Guidelines: code generated by an LLM/similar technology is
|
|
444
|
+
// "presumed to be tainted code, and must not be committed without prior
|
|
445
|
+
// written approval by core". https://www.netbsd.org/developers/commit-guidelines.html
|
|
446
|
+
"NetBSD"
|
|
447
|
+
// NOT listed (checked, deliberately excluded): QEMU's blanket AI-contribution
|
|
448
|
+
// ban is IN FLUX as of 2026-05 — a patch replacing it with a disclosure-based
|
|
449
|
+
// policy ("AI-used-for:" tag) was posted to qemu-devel and appears to have
|
|
450
|
+
// developer buy-in, so it is no longer a clean/current ban to key a hard
|
|
451
|
+
// supply-side drop on. https://www.theregister.com/ai-and-ml/2026/05/29/qemu-mulls-relaxing-ai-contribution-ban/
|
|
452
|
+
];
|
|
453
|
+
AI_BAN_LC = new Set(AI_BAN_DENYLIST.map((g) => g.toLowerCase()));
|
|
454
|
+
}
|
|
455
|
+
});
|
|
456
|
+
|
|
425
457
|
// ../../packages/core/src/feeds/contribution-gate.ts
|
|
426
458
|
var init_contribution_gate = __esm({
|
|
427
459
|
"../../packages/core/src/feeds/contribution-gate.ts"() {
|
|
428
460
|
"use strict";
|
|
461
|
+
init_bounty_gate();
|
|
429
462
|
}
|
|
430
463
|
});
|
|
431
464
|
|
|
@@ -519,23 +552,6 @@ var init_hn = __esm({
|
|
|
519
552
|
}
|
|
520
553
|
});
|
|
521
554
|
|
|
522
|
-
// ../../packages/core/src/feeds/bounty-gate.ts
|
|
523
|
-
var BOUNTY_REPO_DENYLIST, DENYLIST_LC;
|
|
524
|
-
var init_bounty_gate = __esm({
|
|
525
|
-
"../../packages/core/src/feeds/bounty-gate.ts"() {
|
|
526
|
-
"use strict";
|
|
527
|
-
BOUNTY_REPO_DENYLIST = [
|
|
528
|
-
"SecureBananaLabs/bug-bounty",
|
|
529
|
-
// Meta-farm: a bounty PLATFORM whose own issues are an assignment-gated
|
|
530
|
-
// contributor queue ("please assign me, my chief") — an unsolicited PR won't
|
|
531
|
-
// merge, so it's not a real claimable bounty. Not structurally derivable from
|
|
532
|
-
// any fetched field, so it's a manual entry (also dropped from the allowlist).
|
|
533
|
-
"boundlessfi/boundless"
|
|
534
|
-
];
|
|
535
|
-
DENYLIST_LC = new Set(BOUNTY_REPO_DENYLIST.map((r) => r.toLowerCase()));
|
|
536
|
-
}
|
|
537
|
-
});
|
|
538
|
-
|
|
539
555
|
// ../../packages/core/src/concurrency.ts
|
|
540
556
|
var init_concurrency = __esm({
|
|
541
557
|
"../../packages/core/src/concurrency.ts"() {
|
|
@@ -3865,6 +3881,13 @@ var init_legible = __esm({
|
|
|
3865
3881
|
}
|
|
3866
3882
|
});
|
|
3867
3883
|
|
|
3884
|
+
// ../../packages/core/src/credential/legible-trajectory.ts
|
|
3885
|
+
var init_legible_trajectory = __esm({
|
|
3886
|
+
"../../packages/core/src/credential/legible-trajectory.ts"() {
|
|
3887
|
+
"use strict";
|
|
3888
|
+
}
|
|
3889
|
+
});
|
|
3890
|
+
|
|
3868
3891
|
// ../../packages/core/src/short-token.ts
|
|
3869
3892
|
import { createHash as createHash2 } from "crypto";
|
|
3870
3893
|
var init_short_token = __esm({
|
|
@@ -3889,6 +3912,7 @@ var init_src = __esm({
|
|
|
3889
3912
|
init_chatCrypto();
|
|
3890
3913
|
init_job_status();
|
|
3891
3914
|
init_legible();
|
|
3915
|
+
init_legible_trajectory();
|
|
3892
3916
|
init_short_token();
|
|
3893
3917
|
}
|
|
3894
3918
|
});
|
|
@@ -3901,9 +3925,9 @@ var init_keytar = __esm({
|
|
|
3901
3925
|
}
|
|
3902
3926
|
});
|
|
3903
3927
|
|
|
3904
|
-
// node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/3ffac25b-ca95-4a86-9e17-a4cf326551de/scratchpad/
|
|
3928
|
+
// node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/3ffac25b-ca95-4a86-9e17-a4cf326551de/scratchpad/rel2/node_modules/keytar/build/Release/keytar.node
|
|
3905
3929
|
var require_keytar = __commonJS({
|
|
3906
|
-
"node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/3ffac25b-ca95-4a86-9e17-a4cf326551de/scratchpad/
|
|
3930
|
+
"node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/3ffac25b-ca95-4a86-9e17-a4cf326551de/scratchpad/rel2/node_modules/keytar/build/Release/keytar.node"(exports, module) {
|
|
3907
3931
|
"use strict";
|
|
3908
3932
|
init_keytar();
|
|
3909
3933
|
try {
|
package/dist/bin/jpi-chat.js
CHANGED
|
@@ -439,10 +439,43 @@ var init_vocabulary = __esm({
|
|
|
439
439
|
}
|
|
440
440
|
});
|
|
441
441
|
|
|
442
|
+
// ../../packages/core/src/feeds/bounty-gate.ts
|
|
443
|
+
var BOUNTY_REPO_DENYLIST, DENYLIST_LC, AI_BAN_DENYLIST, AI_BAN_LC;
|
|
444
|
+
var init_bounty_gate = __esm({
|
|
445
|
+
"../../packages/core/src/feeds/bounty-gate.ts"() {
|
|
446
|
+
"use strict";
|
|
447
|
+
BOUNTY_REPO_DENYLIST = [
|
|
448
|
+
"SecureBananaLabs/bug-bounty",
|
|
449
|
+
// Meta-farm: a bounty PLATFORM whose own issues are an assignment-gated
|
|
450
|
+
// contributor queue ("please assign me, my chief") — an unsolicited PR won't
|
|
451
|
+
// merge, so it's not a real claimable bounty. Not structurally derivable from
|
|
452
|
+
// any fetched field, so it's a manual entry (also dropped from the allowlist).
|
|
453
|
+
"boundlessfi/boundless"
|
|
454
|
+
];
|
|
455
|
+
DENYLIST_LC = new Set(BOUNTY_REPO_DENYLIST.map((r) => r.toLowerCase()));
|
|
456
|
+
AI_BAN_DENYLIST = [
|
|
457
|
+
// Gentoo Council voted 6-0 (2024-04-14) to ban AI/ML-generated contributions
|
|
458
|
+
// project-wide. https://wiki.gentoo.org/wiki/Project:Council/AI_policy
|
|
459
|
+
"gentoo",
|
|
460
|
+
// NetBSD Commit Guidelines: code generated by an LLM/similar technology is
|
|
461
|
+
// "presumed to be tainted code, and must not be committed without prior
|
|
462
|
+
// written approval by core". https://www.netbsd.org/developers/commit-guidelines.html
|
|
463
|
+
"NetBSD"
|
|
464
|
+
// NOT listed (checked, deliberately excluded): QEMU's blanket AI-contribution
|
|
465
|
+
// ban is IN FLUX as of 2026-05 — a patch replacing it with a disclosure-based
|
|
466
|
+
// policy ("AI-used-for:" tag) was posted to qemu-devel and appears to have
|
|
467
|
+
// developer buy-in, so it is no longer a clean/current ban to key a hard
|
|
468
|
+
// supply-side drop on. https://www.theregister.com/ai-and-ml/2026/05/29/qemu-mulls-relaxing-ai-contribution-ban/
|
|
469
|
+
];
|
|
470
|
+
AI_BAN_LC = new Set(AI_BAN_DENYLIST.map((g) => g.toLowerCase()));
|
|
471
|
+
}
|
|
472
|
+
});
|
|
473
|
+
|
|
442
474
|
// ../../packages/core/src/feeds/contribution-gate.ts
|
|
443
475
|
var init_contribution_gate = __esm({
|
|
444
476
|
"../../packages/core/src/feeds/contribution-gate.ts"() {
|
|
445
477
|
"use strict";
|
|
478
|
+
init_bounty_gate();
|
|
446
479
|
}
|
|
447
480
|
});
|
|
448
481
|
|
|
@@ -536,23 +569,6 @@ var init_hn = __esm({
|
|
|
536
569
|
}
|
|
537
570
|
});
|
|
538
571
|
|
|
539
|
-
// ../../packages/core/src/feeds/bounty-gate.ts
|
|
540
|
-
var BOUNTY_REPO_DENYLIST, DENYLIST_LC;
|
|
541
|
-
var init_bounty_gate = __esm({
|
|
542
|
-
"../../packages/core/src/feeds/bounty-gate.ts"() {
|
|
543
|
-
"use strict";
|
|
544
|
-
BOUNTY_REPO_DENYLIST = [
|
|
545
|
-
"SecureBananaLabs/bug-bounty",
|
|
546
|
-
// Meta-farm: a bounty PLATFORM whose own issues are an assignment-gated
|
|
547
|
-
// contributor queue ("please assign me, my chief") — an unsolicited PR won't
|
|
548
|
-
// merge, so it's not a real claimable bounty. Not structurally derivable from
|
|
549
|
-
// any fetched field, so it's a manual entry (also dropped from the allowlist).
|
|
550
|
-
"boundlessfi/boundless"
|
|
551
|
-
];
|
|
552
|
-
DENYLIST_LC = new Set(BOUNTY_REPO_DENYLIST.map((r) => r.toLowerCase()));
|
|
553
|
-
}
|
|
554
|
-
});
|
|
555
|
-
|
|
556
572
|
// ../../packages/core/src/concurrency.ts
|
|
557
573
|
var init_concurrency = __esm({
|
|
558
574
|
"../../packages/core/src/concurrency.ts"() {
|
|
@@ -3893,6 +3909,13 @@ var init_legible = __esm({
|
|
|
3893
3909
|
}
|
|
3894
3910
|
});
|
|
3895
3911
|
|
|
3912
|
+
// ../../packages/core/src/credential/legible-trajectory.ts
|
|
3913
|
+
var init_legible_trajectory = __esm({
|
|
3914
|
+
"../../packages/core/src/credential/legible-trajectory.ts"() {
|
|
3915
|
+
"use strict";
|
|
3916
|
+
}
|
|
3917
|
+
});
|
|
3918
|
+
|
|
3896
3919
|
// ../../packages/core/src/short-token.ts
|
|
3897
3920
|
import { createHash as createHash2 } from "crypto";
|
|
3898
3921
|
var init_short_token = __esm({
|
|
@@ -3917,6 +3940,7 @@ var init_src = __esm({
|
|
|
3917
3940
|
init_chatCrypto();
|
|
3918
3941
|
init_job_status();
|
|
3919
3942
|
init_legible();
|
|
3943
|
+
init_legible_trajectory();
|
|
3920
3944
|
init_short_token();
|
|
3921
3945
|
}
|
|
3922
3946
|
});
|
|
@@ -3929,9 +3953,9 @@ var init_keytar = __esm({
|
|
|
3929
3953
|
}
|
|
3930
3954
|
});
|
|
3931
3955
|
|
|
3932
|
-
// node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/3ffac25b-ca95-4a86-9e17-a4cf326551de/scratchpad/
|
|
3956
|
+
// node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/3ffac25b-ca95-4a86-9e17-a4cf326551de/scratchpad/rel2/node_modules/keytar/build/Release/keytar.node
|
|
3933
3957
|
var require_keytar = __commonJS({
|
|
3934
|
-
"node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/3ffac25b-ca95-4a86-9e17-a4cf326551de/scratchpad/
|
|
3958
|
+
"node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/3ffac25b-ca95-4a86-9e17-a4cf326551de/scratchpad/rel2/node_modules/keytar/build/Release/keytar.node"(exports, module) {
|
|
3935
3959
|
"use strict";
|
|
3936
3960
|
init_keytar();
|
|
3937
3961
|
try {
|