terminalhire 0.39.9 → 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.
@@ -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
+ };
@@ -0,0 +1,7 @@
1
+ // bin/founder-pin.js
2
+ function isPinnedFounderBounty(j) {
3
+ return j?.bounty?.bountySource === "founder" && j?.bounty?.claimable === true;
4
+ }
5
+ export {
6
+ isPinnedFounderBounty
7
+ };
@@ -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 gate = qualifiesMaintainer(
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 = gate.qualifies ? ranked.find((r) => r.name === gate.bestRepoName) ?? null : null;
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: gate.qualifies,
1278
- bestRepoName: gate.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
@@ -10405,6 +10405,58 @@ var init_state_dir = __esm({
10405
10405
  }
10406
10406
  });
10407
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
+
10408
10460
  // src/test-race-barrier.ts
10409
10461
  import { closeSync as closeSync2, constants as constants2, existsSync, lstatSync, openSync as openSync2 } from "fs";
10410
10462
  import { join as join3 } from "path";
@@ -11072,6 +11124,7 @@ var claims_exports = {};
11072
11124
  __export(claims_exports, {
11073
11125
  PUSHED_CLAIM_FIELDS: () => PUSHED_CLAIM_FIELDS,
11074
11126
  acceptedPRRate: () => acceptedPRRate,
11127
+ countAwaitingFounderApproval: () => countAwaitingFounderApproval,
11075
11128
  findClaim: () => findClaim,
11076
11129
  listClaims: () => listClaims,
11077
11130
  nextPolledState: () => nextPolledState,
@@ -11253,6 +11306,15 @@ function removeClaimIfStakeMatches(id, expectedStakePostedAt) {
11253
11306
  return true;
11254
11307
  });
11255
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
+ }
11256
11318
  function acceptedPRRate(claims = readClaims()) {
11257
11319
  const total = claims.length;
11258
11320
  const merged = claims.filter((c) => c.state === "merged").length;
@@ -11301,44 +11363,52 @@ var init_claims = __esm({
11301
11363
  }
11302
11364
  });
11303
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
+
11304
11404
  // bin/jpi-bounties.js
11305
11405
  init_src();
11406
+ init_cache_store();
11306
11407
  import { readFileSync as readFileSync6 } from "fs";
11307
11408
  import { join as join9 } from "path";
11308
11409
  import { homedir as homedir6 } from "os";
11309
11410
  import { createInterface } from "readline";
11310
11411
 
11311
- // bin/cache-store.js
11312
- init_state_dir();
11313
- import { readFileSync as readFileSync2, writeFileSync, renameSync } from "fs";
11314
- import { join as join2 } from "path";
11315
- import { homedir } from "os";
11316
- var TERMINALHIRE_DIR = process.env.TERMINALHIRE_DIR || join2(homedir(), ".terminalhire");
11317
- var INDEX_CACHE_FILE = join2(TERMINALHIRE_DIR, "index-cache.json");
11318
- var SCHEMA_VERSION2 = 1;
11319
- var tmpCounter = 0;
11320
- function readCacheEntry() {
11321
- try {
11322
- return JSON.parse(readFileSync2(INDEX_CACHE_FILE, "utf8"));
11323
- } catch {
11324
- return null;
11325
- }
11326
- }
11327
- function updateIndexCache(patch) {
11328
- ensureStateDir(TERMINALHIRE_DIR);
11329
- const existing = readCacheEntry() ?? {};
11330
- const entry = {
11331
- ...existing,
11332
- ...patch,
11333
- schemaVersion: SCHEMA_VERSION2,
11334
- ts: Date.now()
11335
- };
11336
- const tmp = `${INDEX_CACHE_FILE}.${process.pid}.${tmpCounter++}.tmp`;
11337
- writeFileSync(tmp, JSON.stringify(entry), "utf8");
11338
- renameSync(tmp, INDEX_CACHE_FILE);
11339
- return entry;
11340
- }
11341
-
11342
11412
  // bin/sanitize.js
11343
11413
  var CONTROL_CHARS = /[\x00-\x1f\x7f-\x9f]/g;
11344
11414
  function sanitizeText(s) {
@@ -11371,6 +11441,7 @@ function linkTitle(title, url) {
11371
11441
  }
11372
11442
 
11373
11443
  // bin/jpi-bounties.js
11444
+ init_founder_pin();
11374
11445
  var TERMINALHIRE_DIR6 = process.env.TERMINALHIRE_DIR || join9(homedir6(), ".terminalhire");
11375
11446
  var INDEX_CACHE_FILE2 = join9(TERMINALHIRE_DIR6, "index-cache.json");
11376
11447
  var INDEX_TTL_MS = 15 * 60 * 1e3;
@@ -11447,9 +11518,6 @@ ${i + 1}. ${linkTitle(job.title, job.url)} [${ref}]`);
11447
11518
  claimed ? ` \u2192 claimed by you \u2014 terminalhire claim status ${job.id}` : ` \u2192 terminalhire claim ${ref}`
11448
11519
  );
11449
11520
  }
11450
- function isPinnedFounderBounty(j) {
11451
- return j?.bounty?.bountySource === "founder" && j?.bounty?.claimable === true;
11452
- }
11453
11521
  function rankBounties(bounties, { rankMode = "winnability", scoreOf = () => 0 } = {}) {
11454
11522
  const legacy = rankMode === "legacy";
11455
11523
  const pin = (j) => isPinnedFounderBounty(j) ? 1 : 0;
@@ -11593,6 +11661,18 @@ async function run() {
11593
11661
  continuityNote
11594
11662
  );
11595
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
+ }
11596
11676
  if (!SHOW_ALL && bounties.length > shown.length) {
11597
11677
  console.log(
11598
11678
  `
@@ -10433,6 +10433,7 @@ var claims_exports = {};
10433
10433
  __export(claims_exports, {
10434
10434
  PUSHED_CLAIM_FIELDS: () => PUSHED_CLAIM_FIELDS,
10435
10435
  acceptedPRRate: () => acceptedPRRate,
10436
+ countAwaitingFounderApproval: () => countAwaitingFounderApproval,
10436
10437
  findClaim: () => findClaim,
10437
10438
  listClaims: () => listClaims,
10438
10439
  nextPolledState: () => nextPolledState,
@@ -10614,6 +10615,15 @@ function removeClaimIfStakeMatches(id, expectedStakePostedAt) {
10614
10615
  return true;
10615
10616
  });
10616
10617
  }
10618
+ function countAwaitingFounderApproval(claims = readClaims()) {
10619
+ try {
10620
+ return claims.filter(
10621
+ (c) => c.approval?.mode === "approval-only" && c.approval?.state === "pending"
10622
+ ).length;
10623
+ } catch {
10624
+ return 0;
10625
+ }
10626
+ }
10617
10627
  function acceptedPRRate(claims = readClaims()) {
10618
10628
  const total = claims.length;
10619
10629
  const merged = claims.filter((c) => c.state === "merged").length;
@@ -25572,6 +25582,83 @@ var init_progress = __esm({
25572
25582
  }
25573
25583
  });
25574
25584
 
25585
+ // bin/approved-claims-badge.js
25586
+ var approved_claims_badge_exports = {};
25587
+ __export(approved_claims_badge_exports, {
25588
+ acknowledgeApprovedClaim: () => acknowledgeApprovedClaim,
25589
+ computeApprovedClaims: () => computeApprovedClaims
25590
+ });
25591
+ function normalizeIds(claimIds) {
25592
+ if (!Array.isArray(claimIds)) return [];
25593
+ return [...new Set(claimIds.filter((id) => typeof id === "string" && id !== ""))].sort();
25594
+ }
25595
+ function computeApprovedClaims(claimIds, previous) {
25596
+ const approved = normalizeIds(claimIds);
25597
+ const prior = previous && Array.isArray(previous.acknowledged) ? new Set(previous.acknowledged) : /* @__PURE__ */ new Set();
25598
+ const acknowledged = approved.filter((id) => prior.has(id));
25599
+ return { count: approved.length - acknowledged.length, acknowledged };
25600
+ }
25601
+ function acknowledgeApprovedClaim(claimId, previous) {
25602
+ const prior = previous && Array.isArray(previous.acknowledged) ? previous.acknowledged : [];
25603
+ if (typeof claimId !== "string" || claimId === "") {
25604
+ const acknowledged2 = [...new Set(prior)].sort();
25605
+ const count2 = previous && typeof previous.count === "number" ? previous.count : 0;
25606
+ return { count: count2, acknowledged: acknowledged2 };
25607
+ }
25608
+ const acknowledged = [.../* @__PURE__ */ new Set([...prior, claimId])].sort();
25609
+ const prevCount = previous && typeof previous.count === "number" ? previous.count : 0;
25610
+ const alreadyKnown = prior.includes(claimId);
25611
+ const count = alreadyKnown ? prevCount : Math.max(0, prevCount - 1);
25612
+ return { count, acknowledged };
25613
+ }
25614
+ var init_approved_claims_badge = __esm({
25615
+ "bin/approved-claims-badge.js"() {
25616
+ "use strict";
25617
+ }
25618
+ });
25619
+
25620
+ // bin/cache-store.js
25621
+ var cache_store_exports = {};
25622
+ __export(cache_store_exports, {
25623
+ readCacheEntry: () => readCacheEntry,
25624
+ updateIndexCache: () => updateIndexCache
25625
+ });
25626
+ import { readFileSync as readFileSync10, writeFileSync as writeFileSync9, renameSync as renameSync5 } from "fs";
25627
+ import { join as join16 } from "path";
25628
+ import { homedir as homedir10 } from "os";
25629
+ function readCacheEntry() {
25630
+ try {
25631
+ return JSON.parse(readFileSync10(INDEX_CACHE_FILE, "utf8"));
25632
+ } catch {
25633
+ return null;
25634
+ }
25635
+ }
25636
+ function updateIndexCache(patch) {
25637
+ ensureStateDir(TERMINALHIRE_DIR10);
25638
+ const existing = readCacheEntry() ?? {};
25639
+ const entry = {
25640
+ ...existing,
25641
+ ...patch,
25642
+ schemaVersion: SCHEMA_VERSION2,
25643
+ ts: Date.now()
25644
+ };
25645
+ const tmp = `${INDEX_CACHE_FILE}.${process.pid}.${tmpCounter++}.tmp`;
25646
+ writeFileSync9(tmp, JSON.stringify(entry), "utf8");
25647
+ renameSync5(tmp, INDEX_CACHE_FILE);
25648
+ return entry;
25649
+ }
25650
+ var TERMINALHIRE_DIR10, INDEX_CACHE_FILE, SCHEMA_VERSION2, tmpCounter;
25651
+ var init_cache_store = __esm({
25652
+ "bin/cache-store.js"() {
25653
+ "use strict";
25654
+ init_state_dir();
25655
+ TERMINALHIRE_DIR10 = process.env.TERMINALHIRE_DIR || join16(homedir10(), ".terminalhire");
25656
+ INDEX_CACHE_FILE = join16(TERMINALHIRE_DIR10, "index-cache.json");
25657
+ SCHEMA_VERSION2 = 1;
25658
+ tmpCounter = 0;
25659
+ }
25660
+ });
25661
+
25575
25662
  // src/acceptance-score.ts
25576
25663
  var acceptance_score_exports = {};
25577
25664
  __export(acceptance_score_exports, {
@@ -25764,9 +25851,9 @@ var init_audit2 = __esm({
25764
25851
 
25765
25852
  // bin/jpi-claim.js
25766
25853
  init_src();
25767
- import { readFileSync as readFileSync10, writeFileSync as writeFileSync9, mkdirSync as mkdirSync3, existsSync as existsSync8, rmSync as rmSync5, readdirSync as readdirSync2 } from "fs";
25768
- import { join as join16, dirname as dirname6, isAbsolute as isAbsolute3, resolve as pathResolve } from "path";
25769
- import { homedir as homedir10, hostname as osHostname } from "os";
25854
+ import { readFileSync as readFileSync11, writeFileSync as writeFileSync10, mkdirSync as mkdirSync3, existsSync as existsSync8, rmSync as rmSync5, readdirSync as readdirSync2 } from "fs";
25855
+ import { join as join17, dirname as dirname6, isAbsolute as isAbsolute3, resolve as pathResolve } from "path";
25856
+ import { homedir as homedir11, hostname as osHostname } from "os";
25770
25857
  import { execFile as execFile3 } from "child_process";
25771
25858
  import { promisify as promisify3 } from "util";
25772
25859
  import { createInterface as createInterface2 } from "readline";
@@ -25944,13 +26031,13 @@ async function shouldNudgeUnpushed() {
25944
26031
  }
25945
26032
 
25946
26033
  // bin/jpi-claim.js
25947
- var TERMINALHIRE_DIR10 = process.env.TERMINALHIRE_DIR || join16(homedir10(), ".terminalhire");
25948
- var INDEX_CACHE_FILE = join16(TERMINALHIRE_DIR10, "index-cache.json");
25949
- var CLAIM_PUSH_MARKER = join16(TERMINALHIRE_DIR10, "claim-push.json");
25950
- var REPO_CONTINUITY_NUDGE_MARKER = join16(TERMINALHIRE_DIR10, "repo-continuity-nudged.json");
26034
+ var TERMINALHIRE_DIR11 = process.env.TERMINALHIRE_DIR || join17(homedir11(), ".terminalhire");
26035
+ var INDEX_CACHE_FILE2 = join17(TERMINALHIRE_DIR11, "index-cache.json");
26036
+ var CLAIM_PUSH_MARKER = join17(TERMINALHIRE_DIR11, "claim-push.json");
26037
+ var REPO_CONTINUITY_NUDGE_MARKER = join17(TERMINALHIRE_DIR11, "repo-continuity-nudged.json");
25951
26038
  function readNudgedClaimIds() {
25952
26039
  try {
25953
- const raw = JSON.parse(readFileSync10(REPO_CONTINUITY_NUDGE_MARKER, "utf8"));
26040
+ const raw = JSON.parse(readFileSync11(REPO_CONTINUITY_NUDGE_MARKER, "utf8"));
25954
26041
  return new Set(Array.isArray(raw.claimIds) ? raw.claimIds : []);
25955
26042
  } catch {
25956
26043
  return /* @__PURE__ */ new Set();
@@ -25960,8 +26047,8 @@ function markClaimNudged(id) {
25960
26047
  try {
25961
26048
  const ids = readNudgedClaimIds();
25962
26049
  ids.add(id);
25963
- ensureStateDir(TERMINALHIRE_DIR10);
25964
- writeFileSync9(REPO_CONTINUITY_NUDGE_MARKER, JSON.stringify({ claimIds: [...ids] }), "utf8");
26050
+ ensureStateDir(TERMINALHIRE_DIR11);
26051
+ writeFileSync10(REPO_CONTINUITY_NUDGE_MARKER, JSON.stringify({ claimIds: [...ids] }), "utf8");
25965
26052
  } catch {
25966
26053
  }
25967
26054
  }
@@ -26169,8 +26256,8 @@ function pickExistingPr(prListJson, ghUser) {
26169
26256
  return match2 && typeof match2.url === "string" ? match2.url : null;
26170
26257
  }
26171
26258
  function readClaimablePool() {
26172
- if (!existsSync8(INDEX_CACHE_FILE)) return [];
26173
- const entry = JSON.parse(readFileSync10(INDEX_CACHE_FILE, "utf8"));
26259
+ if (!existsSync8(INDEX_CACHE_FILE2)) return [];
26260
+ const entry = JSON.parse(readFileSync11(INDEX_CACHE_FILE2, "utf8"));
26174
26261
  const bounties = (entry?.index?.jobs ?? []).filter((j) => j.source === "bounty");
26175
26262
  const contributions = (entry?.index?.contribute ?? []).filter((j) => j.source === "contribute");
26176
26263
  return [...bounties, ...contributions];
@@ -27513,7 +27600,7 @@ async function cmdAttach(id, worktree, branch) {
27513
27600
  function workDirFor(repoFullName, issueNumber) {
27514
27601
  const [owner, repo] = String(repoFullName).split("/");
27515
27602
  const suffix = issueNumber ? `-${issueNumber}` : "";
27516
- return join16(homedir10(), "terminalhire", "work", `${owner}-${repo}${suffix}`);
27603
+ return join17(homedir11(), "terminalhire", "work", `${owner}-${repo}${suffix}`);
27517
27604
  }
27518
27605
  function startBranchFor(repoFullName, issueNumber) {
27519
27606
  const repo = String(repoFullName).split("/")[1] || "claim";
@@ -27630,7 +27717,7 @@ terminalhire claim: not started \u2014 starting forks ${claim.repoFullName} to y
27630
27717
  );
27631
27718
  process.exit(1);
27632
27719
  }
27633
- mkdirSync3(join16(homedir10(), "terminalhire", "work"), { recursive: true });
27720
+ mkdirSync3(join17(homedir11(), "terminalhire", "work"), { recursive: true });
27634
27721
  const { createProgress: createProgress2, parseGitProgress: parseGitProgress2, splitProgressChunk: splitProgressChunk2, shStream: shStream2 } = await Promise.resolve().then(() => (init_progress(), progress_exports));
27635
27722
  const progress = createProgress2();
27636
27723
  let forkFullName;
@@ -27759,7 +27846,7 @@ function founderPostingIdOf(claim) {
27759
27846
  }
27760
27847
  function sliceWorkDirFor(claimLocalId) {
27761
27848
  const safe = String(claimLocalId).replace(/[^A-Za-z0-9._-]/g, "-");
27762
- return join16(homedir10(), "terminalhire", "work", `slice-${safe}`);
27849
+ return join17(homedir11(), "terminalhire", "work", `slice-${safe}`);
27763
27850
  }
27764
27851
  function renderServerRefusal(status, body) {
27765
27852
  const code = body && typeof body.error === "string" ? body.error : null;
@@ -27783,9 +27870,9 @@ function writeSliceFiles(destDir, files) {
27783
27870
  const unavailable = [];
27784
27871
  for (const f of files) {
27785
27872
  if (typeof f.content === "string") {
27786
- const abs = join16(destDir, f.path);
27873
+ const abs = join17(destDir, f.path);
27787
27874
  mkdirSync3(dirname6(abs), { recursive: true });
27788
- writeFileSync9(abs, f.content, "utf8");
27875
+ writeFileSync10(abs, f.content, "utf8");
27789
27876
  written.push(f.path);
27790
27877
  } else {
27791
27878
  unavailable.push({ path: f.path, reason: f.unavailableReason || "(no reason given)" });
@@ -27944,6 +28031,17 @@ async function cmdSlice(id, flags = {}) {
27944
28031
  }
27945
28032
  mkdirSync3(dest, { recursive: true });
27946
28033
  const { written, unavailable } = writeSliceFiles(dest, body.files);
28034
+ try {
28035
+ const { acknowledgeApprovedClaim: acknowledgeApprovedClaim2 } = await Promise.resolve().then(() => (init_approved_claims_badge(), approved_claims_badge_exports));
28036
+ const { readCacheEntry: readCacheEntry2, updateIndexCache: updateIndexCache2 } = await Promise.resolve().then(() => (init_cache_store(), cache_store_exports));
28037
+ updateIndexCache2({
28038
+ approvedClaims: acknowledgeApprovedClaim2(
28039
+ claim.approval.claimId,
28040
+ (readCacheEntry2() ?? {}).approvedClaims
28041
+ )
28042
+ });
28043
+ } catch {
28044
+ }
27947
28045
  console.log(`
27948
28046
  \u2713 Slice received: ${body.title ?? claim.title}`);
27949
28047
  console.log(
@@ -28388,7 +28486,7 @@ async function cmdSubmit(id, flags = {}) {
28388
28486
  const head = `${ghUser}:${claim.branch}`;
28389
28487
  const title = flags.title || claim.title;
28390
28488
  const noBody = Boolean(flags["no-body"]);
28391
- const prBodyPath = join16(wt, "PR-BODY.md");
28489
+ const prBodyPath = join17(wt, "PR-BODY.md");
28392
28490
  const bodySource = pickBodySource({
28393
28491
  bodyFileFlag: flags["body-file"],
28394
28492
  noBody,
@@ -28398,7 +28496,7 @@ async function cmdSubmit(id, flags = {}) {
28398
28496
  let bodyDescr;
28399
28497
  if (bodySource === "body-file") {
28400
28498
  try {
28401
- bodyText = readFileSync10(flags["body-file"], "utf8");
28499
+ bodyText = readFileSync11(flags["body-file"], "utf8");
28402
28500
  } catch (err) {
28403
28501
  console.error(
28404
28502
  `terminalhire claim: could not read --body-file '${flags["body-file"]}': ${err.message ?? err}`
@@ -28407,7 +28505,7 @@ async function cmdSubmit(id, flags = {}) {
28407
28505
  }
28408
28506
  bodyDescr = `--body-file ${flags["body-file"]}`;
28409
28507
  } else if (bodySource === "pr-body") {
28410
- bodyText = readFileSync10(prBodyPath, "utf8");
28508
+ bodyText = readFileSync11(prBodyPath, "utf8");
28411
28509
  bodyDescr = "PR-BODY.md (auto-detected)";
28412
28510
  } else {
28413
28511
  bodyDescr = "(default: Closes + disclosure)";
@@ -28623,14 +28721,14 @@ function claimSleep(ms) {
28623
28721
  }
28624
28722
  function readClaimPushMarker() {
28625
28723
  try {
28626
- return existsSync8(CLAIM_PUSH_MARKER) ? JSON.parse(readFileSync10(CLAIM_PUSH_MARKER, "utf8")) : null;
28724
+ return existsSync8(CLAIM_PUSH_MARKER) ? JSON.parse(readFileSync11(CLAIM_PUSH_MARKER, "utf8")) : null;
28627
28725
  } catch {
28628
28726
  return null;
28629
28727
  }
28630
28728
  }
28631
28729
  function writeClaimPushMarker(marker) {
28632
- ensureStateDir(TERMINALHIRE_DIR10);
28633
- writeFileSync9(CLAIM_PUSH_MARKER, JSON.stringify(marker, null, 2) + "\n", "utf8");
28730
+ ensureStateDir(TERMINALHIRE_DIR11);
28731
+ writeFileSync10(CLAIM_PUSH_MARKER, JSON.stringify(marker, null, 2) + "\n", "utf8");
28634
28732
  }
28635
28733
  function clearClaimPushMarker() {
28636
28734
  try {
@@ -3517,6 +3517,7 @@ var claims_exports = {};
3517
3517
  __export(claims_exports, {
3518
3518
  PUSHED_CLAIM_FIELDS: () => PUSHED_CLAIM_FIELDS,
3519
3519
  acceptedPRRate: () => acceptedPRRate,
3520
+ countAwaitingFounderApproval: () => countAwaitingFounderApproval,
3520
3521
  findClaim: () => findClaim,
3521
3522
  listClaims: () => listClaims,
3522
3523
  nextPolledState: () => nextPolledState,
@@ -3698,6 +3699,15 @@ function removeClaimIfStakeMatches(id, expectedStakePostedAt) {
3698
3699
  return true;
3699
3700
  });
3700
3701
  }
3702
+ function countAwaitingFounderApproval(claims = readClaims()) {
3703
+ try {
3704
+ return claims.filter(
3705
+ (c) => c.approval?.mode === "approval-only" && c.approval?.state === "pending"
3706
+ ).length;
3707
+ } catch {
3708
+ return 0;
3709
+ }
3710
+ }
3701
3711
  function acceptedPRRate(claims = readClaims()) {
3702
3712
  const total = claims.length;
3703
3713
  const merged = claims.filter((c) => c.state === "merged").length;