terminalhire 0.39.8 → 0.40.0
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/README.md +1 -1
- package/dist/bin/approved-claims-badge.js +28 -0
- package/dist/bin/approved-claims-sync.js +51 -0
- package/dist/bin/claim-push-bg.js +10 -0
- package/dist/bin/founder-paid-badge.js +35 -0
- package/dist/bin/founder-pin.js +7 -0
- package/dist/bin/jpi-bounties.js +137 -38
- package/dist/bin/jpi-claim.js +1355 -515
- package/dist/bin/jpi-contribute.js +10 -0
- package/dist/bin/jpi-devs.js +12 -1
- package/dist/bin/jpi-dispatch.js +1633 -365
- package/dist/bin/jpi-hub.js +79 -34
- package/dist/bin/jpi-init.js +21 -8
- package/dist/bin/jpi-jobs.js +15 -3
- package/dist/bin/jpi-login.js +12 -1
- package/dist/bin/jpi-mcp.js +29817 -325
- package/dist/bin/jpi-project.js +12 -1
- package/dist/bin/jpi-refresh.js +300 -43
- package/dist/bin/jpi-repo.js +10 -0
- package/dist/bin/jpi-statusline.js +25 -12
- package/dist/bin/mcp-config.js +7 -5
- package/dist/bin/spinner-render.js +3 -2
- package/dist/bin/spinner.js +3 -2
- package/dist/src/claims.js +10 -0
- package/dist/src/repo-policy.js +40 -3
- package/dist/src/reputation/fetch.js +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -60,7 +60,7 @@ terminalhire trajectory --inward # also show private rework/recovery (never exp
|
|
|
60
60
|
terminalhire devs # opted-in peers & founders — profile never leaves your machine
|
|
61
61
|
terminalhire intro <login> # request a double-opt-in intro (typed-yes consent)
|
|
62
62
|
terminalhire inbox # unread chats, connections & pending intros in one place
|
|
63
|
-
terminalhire mcp --print-config #
|
|
63
|
+
terminalhire mcp --print-config # local-first match + claim-record MCP config for AI hosts
|
|
64
64
|
|
|
65
65
|
terminalhire profile --show # inspect your encrypted local profile (incl. GitHub fields)
|
|
66
66
|
terminalhire profile --edit # set displayName, contactEmail, prefs
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// bin/approved-claims-badge.js
|
|
2
|
+
function normalizeIds(claimIds) {
|
|
3
|
+
if (!Array.isArray(claimIds)) return [];
|
|
4
|
+
return [...new Set(claimIds.filter((id) => typeof id === "string" && id !== ""))].sort();
|
|
5
|
+
}
|
|
6
|
+
function computeApprovedClaims(claimIds, previous) {
|
|
7
|
+
const approved = normalizeIds(claimIds);
|
|
8
|
+
const prior = previous && Array.isArray(previous.acknowledged) ? new Set(previous.acknowledged) : /* @__PURE__ */ new Set();
|
|
9
|
+
const acknowledged = approved.filter((id) => prior.has(id));
|
|
10
|
+
return { count: approved.length - acknowledged.length, acknowledged };
|
|
11
|
+
}
|
|
12
|
+
function acknowledgeApprovedClaim(claimId, previous) {
|
|
13
|
+
const prior = previous && Array.isArray(previous.acknowledged) ? previous.acknowledged : [];
|
|
14
|
+
if (typeof claimId !== "string" || claimId === "") {
|
|
15
|
+
const acknowledged2 = [...new Set(prior)].sort();
|
|
16
|
+
const count2 = previous && typeof previous.count === "number" ? previous.count : 0;
|
|
17
|
+
return { count: count2, acknowledged: acknowledged2 };
|
|
18
|
+
}
|
|
19
|
+
const acknowledged = [.../* @__PURE__ */ new Set([...prior, claimId])].sort();
|
|
20
|
+
const prevCount = previous && typeof previous.count === "number" ? previous.count : 0;
|
|
21
|
+
const alreadyKnown = prior.includes(claimId);
|
|
22
|
+
const count = alreadyKnown ? prevCount : Math.max(0, prevCount - 1);
|
|
23
|
+
return { count, acknowledged };
|
|
24
|
+
}
|
|
25
|
+
export {
|
|
26
|
+
acknowledgeApprovedClaim,
|
|
27
|
+
computeApprovedClaims
|
|
28
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// bin/approved-claims-sync.js
|
|
2
|
+
var CLAIM_SYNC_BASE = "https://terminalhire.com";
|
|
3
|
+
function approvalsSyncGate({ autoMarkerExists, tokenFileExists }) {
|
|
4
|
+
if (!autoMarkerExists || !tokenFileExists) return { sync: false, reason: "not-opted-in" };
|
|
5
|
+
return { sync: true, reason: "ok" };
|
|
6
|
+
}
|
|
7
|
+
function approvalsNudgeGate({ autoMarkerExists, tokenFileExists, awaitingApproval }) {
|
|
8
|
+
if (approvalsSyncGate({ autoMarkerExists, tokenFileExists }).sync) return false;
|
|
9
|
+
return Number.isInteger(awaitingApproval) && awaitingApproval > 0;
|
|
10
|
+
}
|
|
11
|
+
function buildApprovalsNudge(awaitingApproval) {
|
|
12
|
+
if (!Number.isInteger(awaitingApproval) || awaitingApproval <= 0) return null;
|
|
13
|
+
const n = awaitingApproval;
|
|
14
|
+
return ` \u26A0 ${n} claim${n === 1 ? "" : "s"} awaiting founder approval \u2014 terminalhire cannot check in the background until you enrol:
|
|
15
|
+
terminalhire claim --push --keep-updated (or check one now: terminalhire claim slice <id>)`;
|
|
16
|
+
}
|
|
17
|
+
async function syncApprovedClaims({
|
|
18
|
+
readAutoMarker,
|
|
19
|
+
readPushTokenEnc,
|
|
20
|
+
readPrevious,
|
|
21
|
+
fetchImpl = fetch,
|
|
22
|
+
computeApprovedClaims,
|
|
23
|
+
timeoutMs = 15e3
|
|
24
|
+
} = {}) {
|
|
25
|
+
try {
|
|
26
|
+
const marker = readAutoMarker();
|
|
27
|
+
const token = await readPushTokenEnc();
|
|
28
|
+
if (!approvalsSyncGate({ autoMarkerExists: !!marker, tokenFileExists: !!token }).sync) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
const res = await fetchImpl(`${CLAIM_SYNC_BASE}/api/claim/approvals`, {
|
|
32
|
+
method: "POST",
|
|
33
|
+
headers: { "Content-Type": "application/json" },
|
|
34
|
+
body: JSON.stringify({ pushToken: token }),
|
|
35
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
36
|
+
});
|
|
37
|
+
if (!res || !res.ok) return null;
|
|
38
|
+
const body = await res.json();
|
|
39
|
+
const claimIds = body && Array.isArray(body.claimIds) ? body.claimIds : null;
|
|
40
|
+
if (!claimIds) return null;
|
|
41
|
+
return computeApprovedClaims(claimIds, readPrevious());
|
|
42
|
+
} catch {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export {
|
|
47
|
+
approvalsNudgeGate,
|
|
48
|
+
approvalsSyncGate,
|
|
49
|
+
buildApprovalsNudge,
|
|
50
|
+
syncApprovedClaims
|
|
51
|
+
};
|
|
@@ -92,6 +92,7 @@ var claims_exports = {};
|
|
|
92
92
|
__export(claims_exports, {
|
|
93
93
|
PUSHED_CLAIM_FIELDS: () => PUSHED_CLAIM_FIELDS,
|
|
94
94
|
acceptedPRRate: () => acceptedPRRate,
|
|
95
|
+
countAwaitingFounderApproval: () => countAwaitingFounderApproval,
|
|
95
96
|
findClaim: () => findClaim,
|
|
96
97
|
listClaims: () => listClaims,
|
|
97
98
|
nextPolledState: () => nextPolledState,
|
|
@@ -273,6 +274,15 @@ function removeClaimIfStakeMatches(id, expectedStakePostedAt) {
|
|
|
273
274
|
return true;
|
|
274
275
|
});
|
|
275
276
|
}
|
|
277
|
+
function countAwaitingFounderApproval(claims = readClaims()) {
|
|
278
|
+
try {
|
|
279
|
+
return claims.filter(
|
|
280
|
+
(c) => c.approval?.mode === "approval-only" && c.approval?.state === "pending"
|
|
281
|
+
).length;
|
|
282
|
+
} catch {
|
|
283
|
+
return 0;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
276
286
|
function acceptedPRRate(claims = readClaims()) {
|
|
277
287
|
const total = claims.length;
|
|
278
288
|
const merged = claims.filter((c) => c.state === "merged").length;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// bin/founder-pin.js
|
|
2
|
+
function isPinnedFounderBounty(j) {
|
|
3
|
+
return j?.bounty?.bountySource === "founder" && j?.bounty?.claimable === true;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
// bin/founder-paid-badge.js
|
|
7
|
+
function openPaidIds(index) {
|
|
8
|
+
const jobs = index && index.jobs || [];
|
|
9
|
+
const ids = [];
|
|
10
|
+
for (const j of jobs) {
|
|
11
|
+
if (!j || typeof j.id !== "string") continue;
|
|
12
|
+
if (isPinnedFounderBounty(j)) ids.push(j.id);
|
|
13
|
+
}
|
|
14
|
+
return [...new Set(ids)].sort();
|
|
15
|
+
}
|
|
16
|
+
function gate(openIds, seenIds) {
|
|
17
|
+
const seen = new Set(seenIds);
|
|
18
|
+
const acknowledged = openIds.filter((id) => seen.has(id));
|
|
19
|
+
return { count: openIds.length - acknowledged.length, acknowledged };
|
|
20
|
+
}
|
|
21
|
+
function computeFounderPaid(index, previous) {
|
|
22
|
+
const open = openPaidIds(index);
|
|
23
|
+
const prior = previous && previous.acknowledged;
|
|
24
|
+
if (!Array.isArray(prior)) return { count: 0, acknowledged: open };
|
|
25
|
+
return gate(open, prior);
|
|
26
|
+
}
|
|
27
|
+
function acknowledgeFounderPaid({ shown = [], open = [], previous } = {}) {
|
|
28
|
+
const prior = previous && Array.isArray(previous.acknowledged) ? previous.acknowledged : [];
|
|
29
|
+
return gate(openPaidIds({ jobs: open }), [...prior, ...openPaidIds({ jobs: shown })]);
|
|
30
|
+
}
|
|
31
|
+
export {
|
|
32
|
+
acknowledgeFounderPaid,
|
|
33
|
+
computeFounderPaid,
|
|
34
|
+
openPaidIds
|
|
35
|
+
};
|
package/dist/bin/jpi-bounties.js
CHANGED
|
@@ -1258,7 +1258,7 @@ async function fetchOwnedRepoTraction(login, token) {
|
|
|
1258
1258
|
for (const r of enrichCandidates) {
|
|
1259
1259
|
r.externalContributors = await repoExternalContributorCount(login, r.name, login, token);
|
|
1260
1260
|
}
|
|
1261
|
-
const
|
|
1261
|
+
const gate2 = qualifiesMaintainer(
|
|
1262
1262
|
ranked.map((r) => ({
|
|
1263
1263
|
name: r.name,
|
|
1264
1264
|
stars: r.stars,
|
|
@@ -1267,15 +1267,15 @@ async function fetchOwnedRepoTraction(login, token) {
|
|
|
1267
1267
|
fork: false
|
|
1268
1268
|
}))
|
|
1269
1269
|
);
|
|
1270
|
-
const best =
|
|
1270
|
+
const best = gate2.qualifies ? ranked.find((r) => r.name === gate2.bestRepoName) ?? null : null;
|
|
1271
1271
|
return {
|
|
1272
1272
|
status: "ok",
|
|
1273
1273
|
totalStars,
|
|
1274
1274
|
totalForks,
|
|
1275
1275
|
reposWithStars,
|
|
1276
1276
|
top: ranked.slice(0, TRACTION_TOP_N),
|
|
1277
|
-
qualifies:
|
|
1278
|
-
bestRepoName:
|
|
1277
|
+
qualifies: gate2.qualifies,
|
|
1278
|
+
bestRepoName: gate2.bestRepoName,
|
|
1279
1279
|
bestRepoExternalContributors: best ? best.externalContributors : null,
|
|
1280
1280
|
bestRepoStars: best ? best.stars : null,
|
|
1281
1281
|
computedAt
|
|
@@ -1983,6 +1983,7 @@ async function fetchPRScoringFacts(prUrl, token, signal, governor) {
|
|
|
1983
1983
|
mergedAt: pr.merged_at ?? null,
|
|
1984
1984
|
authorId: pr.user?.id ?? null,
|
|
1985
1985
|
authorLogin: pr.user?.login ?? null,
|
|
1986
|
+
authorAssociation: pr.author_association ?? null,
|
|
1986
1987
|
mergedById: pr.merged_by?.id ?? null,
|
|
1987
1988
|
mergedByLogin: pr.merged_by?.login ?? null,
|
|
1988
1989
|
closesIssues,
|
|
@@ -8670,6 +8671,15 @@ function computeEventIndependence(facts) {
|
|
|
8670
8671
|
}
|
|
8671
8672
|
};
|
|
8672
8673
|
}
|
|
8674
|
+
if (facts.authorAssociation != null && AFFILIATED_AUTHOR_ASSOCIATIONS.has(facts.authorAssociation.toUpperCase())) {
|
|
8675
|
+
return {
|
|
8676
|
+
merger: {
|
|
8677
|
+
party: "merger",
|
|
8678
|
+
independence: "affiliated",
|
|
8679
|
+
reasons: [`PR author is affiliated with the target repo (${facts.authorAssociation})`]
|
|
8680
|
+
}
|
|
8681
|
+
};
|
|
8682
|
+
}
|
|
8673
8683
|
return {
|
|
8674
8684
|
merger: {
|
|
8675
8685
|
party: "merger",
|
|
@@ -8700,7 +8710,7 @@ function computeReviewerIndependence(signals) {
|
|
|
8700
8710
|
}
|
|
8701
8711
|
return { party: "reviewer", independence: "unverified", reasons: ["affiliation signal absent (read failed/skipped)"] };
|
|
8702
8712
|
}
|
|
8703
|
-
var PROVENANCE, MS_PER_DAY;
|
|
8713
|
+
var PROVENANCE, MS_PER_DAY, AFFILIATED_AUTHOR_ASSOCIATIONS;
|
|
8704
8714
|
var init_independence = __esm({
|
|
8705
8715
|
"../../packages/core/src/credential/independence.ts"() {
|
|
8706
8716
|
"use strict";
|
|
@@ -8715,6 +8725,7 @@ var init_independence = __esm({
|
|
|
8715
8725
|
CONTRIB_FLOOR: 5
|
|
8716
8726
|
};
|
|
8717
8727
|
MS_PER_DAY = 864e5;
|
|
8728
|
+
AFFILIATED_AUTHOR_ASSOCIATIONS = /* @__PURE__ */ new Set(["OWNER", "MEMBER", "COLLABORATOR"]);
|
|
8718
8729
|
}
|
|
8719
8730
|
});
|
|
8720
8731
|
|
|
@@ -10394,6 +10405,58 @@ var init_state_dir = __esm({
|
|
|
10394
10405
|
}
|
|
10395
10406
|
});
|
|
10396
10407
|
|
|
10408
|
+
// bin/cache-store.js
|
|
10409
|
+
var cache_store_exports = {};
|
|
10410
|
+
__export(cache_store_exports, {
|
|
10411
|
+
readCacheEntry: () => readCacheEntry,
|
|
10412
|
+
updateIndexCache: () => updateIndexCache
|
|
10413
|
+
});
|
|
10414
|
+
import { readFileSync as readFileSync2, writeFileSync, renameSync } from "fs";
|
|
10415
|
+
import { join as join2 } from "path";
|
|
10416
|
+
import { homedir } from "os";
|
|
10417
|
+
function readCacheEntry() {
|
|
10418
|
+
try {
|
|
10419
|
+
return JSON.parse(readFileSync2(INDEX_CACHE_FILE, "utf8"));
|
|
10420
|
+
} catch {
|
|
10421
|
+
return null;
|
|
10422
|
+
}
|
|
10423
|
+
}
|
|
10424
|
+
function updateIndexCache(patch) {
|
|
10425
|
+
ensureStateDir(TERMINALHIRE_DIR);
|
|
10426
|
+
const existing = readCacheEntry() ?? {};
|
|
10427
|
+
const entry = {
|
|
10428
|
+
...existing,
|
|
10429
|
+
...patch,
|
|
10430
|
+
schemaVersion: SCHEMA_VERSION2,
|
|
10431
|
+
ts: Date.now()
|
|
10432
|
+
};
|
|
10433
|
+
const tmp = `${INDEX_CACHE_FILE}.${process.pid}.${tmpCounter++}.tmp`;
|
|
10434
|
+
writeFileSync(tmp, JSON.stringify(entry), "utf8");
|
|
10435
|
+
renameSync(tmp, INDEX_CACHE_FILE);
|
|
10436
|
+
return entry;
|
|
10437
|
+
}
|
|
10438
|
+
var TERMINALHIRE_DIR, INDEX_CACHE_FILE, SCHEMA_VERSION2, tmpCounter;
|
|
10439
|
+
var init_cache_store = __esm({
|
|
10440
|
+
"bin/cache-store.js"() {
|
|
10441
|
+
"use strict";
|
|
10442
|
+
init_state_dir();
|
|
10443
|
+
TERMINALHIRE_DIR = process.env.TERMINALHIRE_DIR || join2(homedir(), ".terminalhire");
|
|
10444
|
+
INDEX_CACHE_FILE = join2(TERMINALHIRE_DIR, "index-cache.json");
|
|
10445
|
+
SCHEMA_VERSION2 = 1;
|
|
10446
|
+
tmpCounter = 0;
|
|
10447
|
+
}
|
|
10448
|
+
});
|
|
10449
|
+
|
|
10450
|
+
// bin/founder-pin.js
|
|
10451
|
+
function isPinnedFounderBounty(j) {
|
|
10452
|
+
return j?.bounty?.bountySource === "founder" && j?.bounty?.claimable === true;
|
|
10453
|
+
}
|
|
10454
|
+
var init_founder_pin = __esm({
|
|
10455
|
+
"bin/founder-pin.js"() {
|
|
10456
|
+
"use strict";
|
|
10457
|
+
}
|
|
10458
|
+
});
|
|
10459
|
+
|
|
10397
10460
|
// src/test-race-barrier.ts
|
|
10398
10461
|
import { closeSync as closeSync2, constants as constants2, existsSync, lstatSync, openSync as openSync2 } from "fs";
|
|
10399
10462
|
import { join as join3 } from "path";
|
|
@@ -11061,6 +11124,7 @@ var claims_exports = {};
|
|
|
11061
11124
|
__export(claims_exports, {
|
|
11062
11125
|
PUSHED_CLAIM_FIELDS: () => PUSHED_CLAIM_FIELDS,
|
|
11063
11126
|
acceptedPRRate: () => acceptedPRRate,
|
|
11127
|
+
countAwaitingFounderApproval: () => countAwaitingFounderApproval,
|
|
11064
11128
|
findClaim: () => findClaim,
|
|
11065
11129
|
listClaims: () => listClaims,
|
|
11066
11130
|
nextPolledState: () => nextPolledState,
|
|
@@ -11242,6 +11306,15 @@ function removeClaimIfStakeMatches(id, expectedStakePostedAt) {
|
|
|
11242
11306
|
return true;
|
|
11243
11307
|
});
|
|
11244
11308
|
}
|
|
11309
|
+
function countAwaitingFounderApproval(claims = readClaims()) {
|
|
11310
|
+
try {
|
|
11311
|
+
return claims.filter(
|
|
11312
|
+
(c) => c.approval?.mode === "approval-only" && c.approval?.state === "pending"
|
|
11313
|
+
).length;
|
|
11314
|
+
} catch {
|
|
11315
|
+
return 0;
|
|
11316
|
+
}
|
|
11317
|
+
}
|
|
11245
11318
|
function acceptedPRRate(claims = readClaims()) {
|
|
11246
11319
|
const total = claims.length;
|
|
11247
11320
|
const merged = claims.filter((c) => c.state === "merged").length;
|
|
@@ -11290,44 +11363,52 @@ var init_claims = __esm({
|
|
|
11290
11363
|
}
|
|
11291
11364
|
});
|
|
11292
11365
|
|
|
11366
|
+
// bin/founder-paid-badge.js
|
|
11367
|
+
var founder_paid_badge_exports = {};
|
|
11368
|
+
__export(founder_paid_badge_exports, {
|
|
11369
|
+
acknowledgeFounderPaid: () => acknowledgeFounderPaid,
|
|
11370
|
+
computeFounderPaid: () => computeFounderPaid,
|
|
11371
|
+
openPaidIds: () => openPaidIds
|
|
11372
|
+
});
|
|
11373
|
+
function openPaidIds(index) {
|
|
11374
|
+
const jobs = index && index.jobs || [];
|
|
11375
|
+
const ids = [];
|
|
11376
|
+
for (const j of jobs) {
|
|
11377
|
+
if (!j || typeof j.id !== "string") continue;
|
|
11378
|
+
if (isPinnedFounderBounty(j)) ids.push(j.id);
|
|
11379
|
+
}
|
|
11380
|
+
return [...new Set(ids)].sort();
|
|
11381
|
+
}
|
|
11382
|
+
function gate(openIds, seenIds) {
|
|
11383
|
+
const seen = new Set(seenIds);
|
|
11384
|
+
const acknowledged = openIds.filter((id) => seen.has(id));
|
|
11385
|
+
return { count: openIds.length - acknowledged.length, acknowledged };
|
|
11386
|
+
}
|
|
11387
|
+
function computeFounderPaid(index, previous) {
|
|
11388
|
+
const open = openPaidIds(index);
|
|
11389
|
+
const prior = previous && previous.acknowledged;
|
|
11390
|
+
if (!Array.isArray(prior)) return { count: 0, acknowledged: open };
|
|
11391
|
+
return gate(open, prior);
|
|
11392
|
+
}
|
|
11393
|
+
function acknowledgeFounderPaid({ shown = [], open = [], previous } = {}) {
|
|
11394
|
+
const prior = previous && Array.isArray(previous.acknowledged) ? previous.acknowledged : [];
|
|
11395
|
+
return gate(openPaidIds({ jobs: open }), [...prior, ...openPaidIds({ jobs: shown })]);
|
|
11396
|
+
}
|
|
11397
|
+
var init_founder_paid_badge = __esm({
|
|
11398
|
+
"bin/founder-paid-badge.js"() {
|
|
11399
|
+
"use strict";
|
|
11400
|
+
init_founder_pin();
|
|
11401
|
+
}
|
|
11402
|
+
});
|
|
11403
|
+
|
|
11293
11404
|
// bin/jpi-bounties.js
|
|
11294
11405
|
init_src();
|
|
11406
|
+
init_cache_store();
|
|
11295
11407
|
import { readFileSync as readFileSync6 } from "fs";
|
|
11296
11408
|
import { join as join9 } from "path";
|
|
11297
11409
|
import { homedir as homedir6 } from "os";
|
|
11298
11410
|
import { createInterface } from "readline";
|
|
11299
11411
|
|
|
11300
|
-
// bin/cache-store.js
|
|
11301
|
-
init_state_dir();
|
|
11302
|
-
import { readFileSync as readFileSync2, writeFileSync, renameSync } from "fs";
|
|
11303
|
-
import { join as join2 } from "path";
|
|
11304
|
-
import { homedir } from "os";
|
|
11305
|
-
var TERMINALHIRE_DIR = process.env.TERMINALHIRE_DIR || join2(homedir(), ".terminalhire");
|
|
11306
|
-
var INDEX_CACHE_FILE = join2(TERMINALHIRE_DIR, "index-cache.json");
|
|
11307
|
-
var SCHEMA_VERSION2 = 1;
|
|
11308
|
-
var tmpCounter = 0;
|
|
11309
|
-
function readCacheEntry() {
|
|
11310
|
-
try {
|
|
11311
|
-
return JSON.parse(readFileSync2(INDEX_CACHE_FILE, "utf8"));
|
|
11312
|
-
} catch {
|
|
11313
|
-
return null;
|
|
11314
|
-
}
|
|
11315
|
-
}
|
|
11316
|
-
function updateIndexCache(patch) {
|
|
11317
|
-
ensureStateDir(TERMINALHIRE_DIR);
|
|
11318
|
-
const existing = readCacheEntry() ?? {};
|
|
11319
|
-
const entry = {
|
|
11320
|
-
...existing,
|
|
11321
|
-
...patch,
|
|
11322
|
-
schemaVersion: SCHEMA_VERSION2,
|
|
11323
|
-
ts: Date.now()
|
|
11324
|
-
};
|
|
11325
|
-
const tmp = `${INDEX_CACHE_FILE}.${process.pid}.${tmpCounter++}.tmp`;
|
|
11326
|
-
writeFileSync(tmp, JSON.stringify(entry), "utf8");
|
|
11327
|
-
renameSync(tmp, INDEX_CACHE_FILE);
|
|
11328
|
-
return entry;
|
|
11329
|
-
}
|
|
11330
|
-
|
|
11331
11412
|
// bin/sanitize.js
|
|
11332
11413
|
var CONTROL_CHARS = /[\x00-\x1f\x7f-\x9f]/g;
|
|
11333
11414
|
function sanitizeText(s) {
|
|
@@ -11360,6 +11441,7 @@ function linkTitle(title, url) {
|
|
|
11360
11441
|
}
|
|
11361
11442
|
|
|
11362
11443
|
// bin/jpi-bounties.js
|
|
11444
|
+
init_founder_pin();
|
|
11363
11445
|
var TERMINALHIRE_DIR6 = process.env.TERMINALHIRE_DIR || join9(homedir6(), ".terminalhire");
|
|
11364
11446
|
var INDEX_CACHE_FILE2 = join9(TERMINALHIRE_DIR6, "index-cache.json");
|
|
11365
11447
|
var INDEX_TTL_MS = 15 * 60 * 1e3;
|
|
@@ -11438,6 +11520,7 @@ ${i + 1}. ${linkTitle(job.title, job.url)} [${ref}]`);
|
|
|
11438
11520
|
}
|
|
11439
11521
|
function rankBounties(bounties, { rankMode = "winnability", scoreOf = () => 0 } = {}) {
|
|
11440
11522
|
const legacy = rankMode === "legacy";
|
|
11523
|
+
const pin = (j) => isPinnedFounderBounty(j) ? 1 : 0;
|
|
11441
11524
|
const contested = (j) => (j.bounty?.competingOpenPRs ?? 0) > 0 ? 1 : 0;
|
|
11442
11525
|
const amt = (j) => j.bounty?.amountUSD ?? -1;
|
|
11443
11526
|
const winTier = (j) => {
|
|
@@ -11447,12 +11530,13 @@ function rankBounties(bounties, { rankMode = "winnability", scoreOf = () => 0 }
|
|
|
11447
11530
|
};
|
|
11448
11531
|
const winVal = (j) => j.winnabilityScore ?? 0;
|
|
11449
11532
|
bounties.sort(
|
|
11450
|
-
(a, b) => (legacy ? 0 : winTier(b) - winTier(a)) || (legacy ? 0 : winVal(b) - winVal(a)) || contested(a) - contested(b) || scoreOf(b) - scoreOf(a) || amt(b) - amt(a)
|
|
11533
|
+
(a, b) => pin(b) - pin(a) || (legacy ? 0 : winTier(b) - winTier(a)) || (legacy ? 0 : winVal(b) - winVal(a)) || contested(a) - contested(b) || scoreOf(b) - scoreOf(a) || amt(b) - amt(a)
|
|
11451
11534
|
);
|
|
11452
11535
|
return bounties;
|
|
11453
11536
|
}
|
|
11454
11537
|
function applyContinuityRank(bounties, continuityOf, { enabled = true } = {}) {
|
|
11455
11538
|
if (!enabled) return bounties;
|
|
11539
|
+
const pin = (j) => isPinnedFounderBounty(j) ? 1 : 0;
|
|
11456
11540
|
const winTier = (j) => {
|
|
11457
11541
|
const s = j.winnabilityScore;
|
|
11458
11542
|
if (s == null) return 1;
|
|
@@ -11464,7 +11548,9 @@ function applyContinuityRank(bounties, continuityOf, { enabled = true } = {}) {
|
|
|
11464
11548
|
const c = repo ? continuityOf(repo) || 0 : 0;
|
|
11465
11549
|
return s * (1 + 0.15 * c);
|
|
11466
11550
|
};
|
|
11467
|
-
bounties.sort(
|
|
11551
|
+
bounties.sort(
|
|
11552
|
+
(a, b) => pin(b) - pin(a) || winTier(b) - winTier(a) || effectiveVal(b) - effectiveVal(a)
|
|
11553
|
+
);
|
|
11468
11554
|
return bounties;
|
|
11469
11555
|
}
|
|
11470
11556
|
function continuityNoteForRow(entry, isTTY) {
|
|
@@ -11575,6 +11661,18 @@ async function run() {
|
|
|
11575
11661
|
continuityNote
|
|
11576
11662
|
);
|
|
11577
11663
|
}
|
|
11664
|
+
try {
|
|
11665
|
+
const { acknowledgeFounderPaid: acknowledgeFounderPaid2 } = await Promise.resolve().then(() => (init_founder_paid_badge(), founder_paid_badge_exports));
|
|
11666
|
+
const { readCacheEntry: readCacheEntry2 } = await Promise.resolve().then(() => (init_cache_store(), cache_store_exports));
|
|
11667
|
+
updateIndexCache({
|
|
11668
|
+
founderPaid: acknowledgeFounderPaid2({
|
|
11669
|
+
shown,
|
|
11670
|
+
open: bounties,
|
|
11671
|
+
previous: (readCacheEntry2() ?? {}).founderPaid
|
|
11672
|
+
})
|
|
11673
|
+
});
|
|
11674
|
+
} catch {
|
|
11675
|
+
}
|
|
11578
11676
|
if (!SHOW_ALL && bounties.length > shown.length) {
|
|
11579
11677
|
console.log(
|
|
11580
11678
|
`
|
|
@@ -11606,6 +11704,7 @@ export {
|
|
|
11606
11704
|
continuityNoteForRow,
|
|
11607
11705
|
filterPaidVisibility,
|
|
11608
11706
|
getBounties,
|
|
11707
|
+
isPinnedFounderBounty,
|
|
11609
11708
|
printBounty,
|
|
11610
11709
|
rankBounties,
|
|
11611
11710
|
run
|