terminalhire 0.41.0 → 0.41.1

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.
@@ -26056,6 +26056,13 @@ function openInBrowser(url) {
26056
26056
  }
26057
26057
  }
26058
26058
 
26059
+ // bin/sanitize.js
26060
+ var CONTROL_CHARS = /[\x00-\x1f\x7f-\x9f]/g;
26061
+ function sanitizeText(s) {
26062
+ if (s == null) return "";
26063
+ return String(s).replace(CONTROL_CHARS, "");
26064
+ }
26065
+
26059
26066
  // src/policy-acks.ts
26060
26067
  init_state_dir();
26061
26068
  import { lstatSync, readFileSync as readFileSync2, writeFileSync } from "fs";
@@ -28307,35 +28314,61 @@ async function ensureForkExists(repoFullName, ghUser) {
28307
28314
  if (!isFork) throw new Error(`fork ${forkFullName} created but could not be verified as a fork`);
28308
28315
  return forkFullName;
28309
28316
  }
28317
+ function shouldStatePending(claim, approvalsChecked) {
28318
+ return Boolean(claim?.approval) && claim.approval.state === "pending" && Boolean(approvalsChecked);
28319
+ }
28320
+ function startableRow(c) {
28321
+ const bits = [fmtClaimAmount(c), sanitizeText(c.title)];
28322
+ if (c.repoFullName) bits.push(sanitizeText(c.repoFullName));
28323
+ return bits.join(" \xB7 ");
28324
+ }
28325
+ async function pickStartableClaim(claims, { prompt = ask, isTTY = process.stdin.isTTY } = {}) {
28326
+ const active = claims.listClaims({ active: true });
28327
+ await syncFounderApprovals(claims, active);
28328
+ const startable = claims.listClaims({ active: true }).filter((c) => c.state === "claimed");
28329
+ if (startable.length === 0) {
28330
+ console.log("No claims ready to start. Claim one first: terminalhire claim <ref>");
28331
+ return null;
28332
+ }
28333
+ const interactive = Boolean(isTTY);
28334
+ console.log(`
28335
+ ${startable.length} claim${startable.length === 1 ? "" : "s"} ready to start:
28336
+ `);
28337
+ const width = String(startable.length).length;
28338
+ startable.forEach((c, i) => {
28339
+ console.log(` ${String(i + 1).padStart(width)}) ${startableRow(c)}`);
28340
+ if (!interactive) console.log(` terminalhire claim start ${c.id}`);
28341
+ });
28342
+ if (!interactive) {
28343
+ console.log("\nRun the command under the one you want to start.");
28344
+ return null;
28345
+ }
28346
+ const answer = await prompt(`
28347
+ Which one? (1-${startable.length}, or q to quit) `);
28348
+ if (answer === "" || /^q(uit)?$/i.test(answer)) return null;
28349
+ const n = Number.parseInt(answer, 10);
28350
+ if (!/^\d+$/.test(answer) || !Number.isInteger(n) || n < 1 || n > startable.length) {
28351
+ console.log(`
28352
+ Nothing started \u2014 '${answer}' is not one of 1-${startable.length}.`);
28353
+ return null;
28354
+ }
28355
+ return startable[n - 1].id;
28356
+ }
28310
28357
  async function cmdStart(id, flags = {}) {
28311
28358
  const claims = await Promise.resolve().then(() => (init_claims(), claims_exports));
28312
28359
  if (!id) {
28313
- let list = claims.listClaims({ active: true });
28314
- await syncFounderApprovals(claims, list);
28315
- const startable = claims.listClaims({ active: true }).filter((c) => c.state === "claimed");
28316
- if (startable.length === 0) {
28317
- console.log("No claims ready to start. Claim one first: terminalhire claim <ref>");
28318
- return;
28319
- }
28320
- console.log(
28321
- `
28322
- ${startable.length} claim${startable.length === 1 ? "" : "s"} ready to start:
28323
- `
28324
- );
28325
- for (const c of startable) {
28326
- console.log(` ${c.title}`);
28327
- console.log(` terminalhire claim start ${c.id}`);
28328
- }
28329
- console.log("\nRun the command under the one you want to start.");
28330
- return;
28360
+ const picked = await pickStartableClaim(claims);
28361
+ if (!picked) return;
28362
+ id = picked;
28331
28363
  }
28332
28364
  let claim = claims.findClaim(id);
28333
28365
  if (!claim) {
28334
28366
  console.error(`terminalhire claim: no claim with id '${id}'.`);
28335
28367
  process.exit(1);
28336
28368
  }
28369
+ let approvalsChecked = false;
28337
28370
  if (claim.approval?.state === "pending") {
28338
- await syncFounderApprovals(claims, [claim]);
28371
+ ({ approvalsChecked } = await syncFounderApprovals(claims, [claim]));
28339
28372
  claim = claims.findClaim(id);
28340
28373
  }
28341
28374
  if (claim.worktreePath) {
@@ -28356,19 +28389,14 @@ When it's done: terminalhire claim submit ${id}`);
28356
28389
  }
28357
28390
  if (claim.approval) {
28358
28391
  console.log(`
28359
- ${claim.title}`);
28360
- if (claim.approval.state === "pending") {
28361
- console.log(
28362
- "\n Access is pending \u2014 this approval-only posting needs the founder to approve"
28363
- );
28364
- console.log(" your claim before any work can be delivered. No fork was attempted: founder");
28365
- console.log(" postings are never forked or cloned; once approved, your work slice is");
28366
- console.log(" delivered through terminalhire.");
28367
- } else {
28368
- console.log("\n No fork was attempted \u2014 founder postings are never forked or cloned. Your");
28369
- console.log(" work slice is delivered through terminalhire, and your patch goes back the");
28370
- console.log(" same way.");
28371
- }
28392
+ ${sanitizeText(claim.title)}`);
28393
+ console.log("\n No fork was attempted \u2014 founder postings are never forked or cloned. Your");
28394
+ console.log(" work slice is delivered through terminalhire, and your patch goes back the");
28395
+ console.log(" same way.");
28396
+ if (shouldStatePending(claim, approvalsChecked)) {
28397
+ console.log("\n Access is pending \u2014 the founder has not approved your claim yet.");
28398
+ }
28399
+ printNextSteps([claim]);
28372
28400
  return;
28373
28401
  }
28374
28402
  if (flags.here) {
@@ -28618,10 +28646,10 @@ var CLAIM_EVENT_LABEL = {
28618
28646
  rejected: "the founder rejected"
28619
28647
  };
28620
28648
  var LINE_BREAKS = /\r\n|[\r\n\v\f\u0085\u2028\u2029]/;
28621
- var CONTROL_CHARS = /[\u0000-\u001F\u007F-\u009F]/g;
28649
+ var CONTROL_CHARS2 = /[\u0000-\u001F\u007F-\u009F]/g;
28622
28650
  function terminalSafeLines(raw) {
28623
28651
  if (typeof raw !== "string" || raw === "") return [];
28624
- return raw.split(LINE_BREAKS).map((l) => l.replace(CONTROL_CHARS, ""));
28652
+ return raw.split(LINE_BREAKS).map((l) => l.replace(CONTROL_CHARS2, ""));
28625
28653
  }
28626
28654
  function terminalSafeInline(raw) {
28627
28655
  return terminalSafeLines(raw).join(" ");
@@ -30066,6 +30094,7 @@ export {
30066
30094
  normalizeIntent,
30067
30095
  pickBodySource,
30068
30096
  pickExistingPr,
30097
+ pickStartableClaim,
30069
30098
  printNextSteps,
30070
30099
  readCredentialDisposition,
30071
30100
  renderClaimHistory,
@@ -30081,6 +30110,7 @@ export {
30081
30110
  selectCompetingPrs,
30082
30111
  selectPushRemote,
30083
30112
  shouldRequestAssignment,
30113
+ shouldStatePending,
30084
30114
  sliceWorkDirFor,
30085
30115
  stakeDecision,
30086
30116
  startBranchFor,
@@ -30909,6 +30909,7 @@ __export(jpi_claim_exports, {
30909
30909
  normalizeIntent: () => normalizeIntent,
30910
30910
  pickBodySource: () => pickBodySource,
30911
30911
  pickExistingPr: () => pickExistingPr,
30912
+ pickStartableClaim: () => pickStartableClaim,
30912
30913
  printNextSteps: () => printNextSteps,
30913
30914
  readCredentialDisposition: () => readCredentialDisposition,
30914
30915
  renderClaimHistory: () => renderClaimHistory,
@@ -30924,6 +30925,7 @@ __export(jpi_claim_exports, {
30924
30925
  selectCompetingPrs: () => selectCompetingPrs,
30925
30926
  selectPushRemote: () => selectPushRemote,
30926
30927
  shouldRequestAssignment: () => shouldRequestAssignment,
30928
+ shouldStatePending: () => shouldStatePending,
30927
30929
  sliceWorkDirFor: () => sliceWorkDirFor,
30928
30930
  stakeDecision: () => stakeDecision,
30929
30931
  startBranchFor: () => startBranchFor,
@@ -32890,35 +32892,61 @@ async function ensureForkExists(repoFullName, ghUser) {
32890
32892
  if (!isFork) throw new Error(`fork ${forkFullName} created but could not be verified as a fork`);
32891
32893
  return forkFullName;
32892
32894
  }
32895
+ function shouldStatePending(claim, approvalsChecked) {
32896
+ return Boolean(claim?.approval) && claim.approval.state === "pending" && Boolean(approvalsChecked);
32897
+ }
32898
+ function startableRow(c) {
32899
+ const bits = [fmtClaimAmount(c), sanitizeText(c.title)];
32900
+ if (c.repoFullName) bits.push(sanitizeText(c.repoFullName));
32901
+ return bits.join(" \xB7 ");
32902
+ }
32903
+ async function pickStartableClaim(claims, { prompt: prompt5 = ask, isTTY = process.stdin.isTTY } = {}) {
32904
+ const active = claims.listClaims({ active: true });
32905
+ await syncFounderApprovals(claims, active);
32906
+ const startable = claims.listClaims({ active: true }).filter((c) => c.state === "claimed");
32907
+ if (startable.length === 0) {
32908
+ console.log("No claims ready to start. Claim one first: terminalhire claim <ref>");
32909
+ return null;
32910
+ }
32911
+ const interactive = Boolean(isTTY);
32912
+ console.log(`
32913
+ ${startable.length} claim${startable.length === 1 ? "" : "s"} ready to start:
32914
+ `);
32915
+ const width = String(startable.length).length;
32916
+ startable.forEach((c, i) => {
32917
+ console.log(` ${String(i + 1).padStart(width)}) ${startableRow(c)}`);
32918
+ if (!interactive) console.log(` terminalhire claim start ${c.id}`);
32919
+ });
32920
+ if (!interactive) {
32921
+ console.log("\nRun the command under the one you want to start.");
32922
+ return null;
32923
+ }
32924
+ const answer = await prompt5(`
32925
+ Which one? (1-${startable.length}, or q to quit) `);
32926
+ if (answer === "" || /^q(uit)?$/i.test(answer)) return null;
32927
+ const n = Number.parseInt(answer, 10);
32928
+ if (!/^\d+$/.test(answer) || !Number.isInteger(n) || n < 1 || n > startable.length) {
32929
+ console.log(`
32930
+ Nothing started \u2014 '${answer}' is not one of 1-${startable.length}.`);
32931
+ return null;
32932
+ }
32933
+ return startable[n - 1].id;
32934
+ }
32893
32935
  async function cmdStart(id, flags = {}) {
32894
32936
  const claims = await Promise.resolve().then(() => (init_claims(), claims_exports));
32895
32937
  if (!id) {
32896
- let list = claims.listClaims({ active: true });
32897
- await syncFounderApprovals(claims, list);
32898
- const startable = claims.listClaims({ active: true }).filter((c) => c.state === "claimed");
32899
- if (startable.length === 0) {
32900
- console.log("No claims ready to start. Claim one first: terminalhire claim <ref>");
32901
- return;
32902
- }
32903
- console.log(
32904
- `
32905
- ${startable.length} claim${startable.length === 1 ? "" : "s"} ready to start:
32906
- `
32907
- );
32908
- for (const c of startable) {
32909
- console.log(` ${c.title}`);
32910
- console.log(` terminalhire claim start ${c.id}`);
32911
- }
32912
- console.log("\nRun the command under the one you want to start.");
32913
- return;
32938
+ const picked = await pickStartableClaim(claims);
32939
+ if (!picked) return;
32940
+ id = picked;
32914
32941
  }
32915
32942
  let claim = claims.findClaim(id);
32916
32943
  if (!claim) {
32917
32944
  console.error(`terminalhire claim: no claim with id '${id}'.`);
32918
32945
  process.exit(1);
32919
32946
  }
32947
+ let approvalsChecked = false;
32920
32948
  if (claim.approval?.state === "pending") {
32921
- await syncFounderApprovals(claims, [claim]);
32949
+ ({ approvalsChecked } = await syncFounderApprovals(claims, [claim]));
32922
32950
  claim = claims.findClaim(id);
32923
32951
  }
32924
32952
  if (claim.worktreePath) {
@@ -32939,19 +32967,14 @@ When it's done: terminalhire claim submit ${id}`);
32939
32967
  }
32940
32968
  if (claim.approval) {
32941
32969
  console.log(`
32942
- ${claim.title}`);
32943
- if (claim.approval.state === "pending") {
32944
- console.log(
32945
- "\n Access is pending \u2014 this approval-only posting needs the founder to approve"
32946
- );
32947
- console.log(" your claim before any work can be delivered. No fork was attempted: founder");
32948
- console.log(" postings are never forked or cloned; once approved, your work slice is");
32949
- console.log(" delivered through terminalhire.");
32950
- } else {
32951
- console.log("\n No fork was attempted \u2014 founder postings are never forked or cloned. Your");
32952
- console.log(" work slice is delivered through terminalhire, and your patch goes back the");
32953
- console.log(" same way.");
32954
- }
32970
+ ${sanitizeText(claim.title)}`);
32971
+ console.log("\n No fork was attempted \u2014 founder postings are never forked or cloned. Your");
32972
+ console.log(" work slice is delivered through terminalhire, and your patch goes back the");
32973
+ console.log(" same way.");
32974
+ if (shouldStatePending(claim, approvalsChecked)) {
32975
+ console.log("\n Access is pending \u2014 the founder has not approved your claim yet.");
32976
+ }
32977
+ printNextSteps([claim]);
32955
32978
  return;
32956
32979
  }
32957
32980
  if (flags.here) {
@@ -34599,6 +34622,7 @@ var init_jpi_claim = __esm({
34599
34622
  "use strict";
34600
34623
  init_src();
34601
34624
  init_open_url();
34625
+ init_sanitize();
34602
34626
  init_policy_acks();
34603
34627
  init_claims();
34604
34628
  init_state_dir();
@@ -10977,6 +10977,19 @@ var init_open_url = __esm({
10977
10977
  }
10978
10978
  });
10979
10979
 
10980
+ // bin/sanitize.js
10981
+ function sanitizeText(s) {
10982
+ if (s == null) return "";
10983
+ return String(s).replace(CONTROL_CHARS, "");
10984
+ }
10985
+ var CONTROL_CHARS;
10986
+ var init_sanitize = __esm({
10987
+ "bin/sanitize.js"() {
10988
+ "use strict";
10989
+ CONTROL_CHARS = /[\x00-\x1f\x7f-\x9f]/g;
10990
+ }
10991
+ });
10992
+
10980
10993
  // src/policy-acks.ts
10981
10994
  var policy_acks_exports = {};
10982
10995
  __export(policy_acks_exports, {
@@ -26374,6 +26387,7 @@ __export(jpi_claim_exports, {
26374
26387
  normalizeIntent: () => normalizeIntent,
26375
26388
  pickBodySource: () => pickBodySource,
26376
26389
  pickExistingPr: () => pickExistingPr,
26390
+ pickStartableClaim: () => pickStartableClaim,
26377
26391
  printNextSteps: () => printNextSteps,
26378
26392
  readCredentialDisposition: () => readCredentialDisposition,
26379
26393
  renderClaimHistory: () => renderClaimHistory,
@@ -26389,6 +26403,7 @@ __export(jpi_claim_exports, {
26389
26403
  selectCompetingPrs: () => selectCompetingPrs,
26390
26404
  selectPushRemote: () => selectPushRemote,
26391
26405
  shouldRequestAssignment: () => shouldRequestAssignment,
26406
+ shouldStatePending: () => shouldStatePending,
26392
26407
  sliceWorkDirFor: () => sliceWorkDirFor,
26393
26408
  stakeDecision: () => stakeDecision,
26394
26409
  startBranchFor: () => startBranchFor,
@@ -28355,35 +28370,61 @@ async function ensureForkExists(repoFullName, ghUser) {
28355
28370
  if (!isFork) throw new Error(`fork ${forkFullName} created but could not be verified as a fork`);
28356
28371
  return forkFullName;
28357
28372
  }
28373
+ function shouldStatePending(claim, approvalsChecked) {
28374
+ return Boolean(claim?.approval) && claim.approval.state === "pending" && Boolean(approvalsChecked);
28375
+ }
28376
+ function startableRow(c) {
28377
+ const bits = [fmtClaimAmount(c), sanitizeText(c.title)];
28378
+ if (c.repoFullName) bits.push(sanitizeText(c.repoFullName));
28379
+ return bits.join(" \xB7 ");
28380
+ }
28381
+ async function pickStartableClaim(claims, { prompt = ask, isTTY = process.stdin.isTTY } = {}) {
28382
+ const active = claims.listClaims({ active: true });
28383
+ await syncFounderApprovals(claims, active);
28384
+ const startable = claims.listClaims({ active: true }).filter((c) => c.state === "claimed");
28385
+ if (startable.length === 0) {
28386
+ console.log("No claims ready to start. Claim one first: terminalhire claim <ref>");
28387
+ return null;
28388
+ }
28389
+ const interactive = Boolean(isTTY);
28390
+ console.log(`
28391
+ ${startable.length} claim${startable.length === 1 ? "" : "s"} ready to start:
28392
+ `);
28393
+ const width = String(startable.length).length;
28394
+ startable.forEach((c, i) => {
28395
+ console.log(` ${String(i + 1).padStart(width)}) ${startableRow(c)}`);
28396
+ if (!interactive) console.log(` terminalhire claim start ${c.id}`);
28397
+ });
28398
+ if (!interactive) {
28399
+ console.log("\nRun the command under the one you want to start.");
28400
+ return null;
28401
+ }
28402
+ const answer = await prompt(`
28403
+ Which one? (1-${startable.length}, or q to quit) `);
28404
+ if (answer === "" || /^q(uit)?$/i.test(answer)) return null;
28405
+ const n = Number.parseInt(answer, 10);
28406
+ if (!/^\d+$/.test(answer) || !Number.isInteger(n) || n < 1 || n > startable.length) {
28407
+ console.log(`
28408
+ Nothing started \u2014 '${answer}' is not one of 1-${startable.length}.`);
28409
+ return null;
28410
+ }
28411
+ return startable[n - 1].id;
28412
+ }
28358
28413
  async function cmdStart(id, flags = {}) {
28359
28414
  const claims = await Promise.resolve().then(() => (init_claims(), claims_exports));
28360
28415
  if (!id) {
28361
- let list = claims.listClaims({ active: true });
28362
- await syncFounderApprovals(claims, list);
28363
- const startable = claims.listClaims({ active: true }).filter((c) => c.state === "claimed");
28364
- if (startable.length === 0) {
28365
- console.log("No claims ready to start. Claim one first: terminalhire claim <ref>");
28366
- return;
28367
- }
28368
- console.log(
28369
- `
28370
- ${startable.length} claim${startable.length === 1 ? "" : "s"} ready to start:
28371
- `
28372
- );
28373
- for (const c of startable) {
28374
- console.log(` ${c.title}`);
28375
- console.log(` terminalhire claim start ${c.id}`);
28376
- }
28377
- console.log("\nRun the command under the one you want to start.");
28378
- return;
28416
+ const picked = await pickStartableClaim(claims);
28417
+ if (!picked) return;
28418
+ id = picked;
28379
28419
  }
28380
28420
  let claim = claims.findClaim(id);
28381
28421
  if (!claim) {
28382
28422
  console.error(`terminalhire claim: no claim with id '${id}'.`);
28383
28423
  process.exit(1);
28384
28424
  }
28425
+ let approvalsChecked = false;
28385
28426
  if (claim.approval?.state === "pending") {
28386
- await syncFounderApprovals(claims, [claim]);
28427
+ ({ approvalsChecked } = await syncFounderApprovals(claims, [claim]));
28387
28428
  claim = claims.findClaim(id);
28388
28429
  }
28389
28430
  if (claim.worktreePath) {
@@ -28404,19 +28445,14 @@ When it's done: terminalhire claim submit ${id}`);
28404
28445
  }
28405
28446
  if (claim.approval) {
28406
28447
  console.log(`
28407
- ${claim.title}`);
28408
- if (claim.approval.state === "pending") {
28409
- console.log(
28410
- "\n Access is pending \u2014 this approval-only posting needs the founder to approve"
28411
- );
28412
- console.log(" your claim before any work can be delivered. No fork was attempted: founder");
28413
- console.log(" postings are never forked or cloned; once approved, your work slice is");
28414
- console.log(" delivered through terminalhire.");
28415
- } else {
28416
- console.log("\n No fork was attempted \u2014 founder postings are never forked or cloned. Your");
28417
- console.log(" work slice is delivered through terminalhire, and your patch goes back the");
28418
- console.log(" same way.");
28419
- }
28448
+ ${sanitizeText(claim.title)}`);
28449
+ console.log("\n No fork was attempted \u2014 founder postings are never forked or cloned. Your");
28450
+ console.log(" work slice is delivered through terminalhire, and your patch goes back the");
28451
+ console.log(" same way.");
28452
+ if (shouldStatePending(claim, approvalsChecked)) {
28453
+ console.log("\n Access is pending \u2014 the founder has not approved your claim yet.");
28454
+ }
28455
+ printNextSteps([claim]);
28420
28456
  return;
28421
28457
  }
28422
28458
  if (flags.here) {
@@ -28654,7 +28690,7 @@ function renderRunView(run3, message) {
28654
28690
  }
28655
28691
  function terminalSafeLines(raw) {
28656
28692
  if (typeof raw !== "string" || raw === "") return [];
28657
- return raw.split(LINE_BREAKS).map((l) => l.replace(CONTROL_CHARS, ""));
28693
+ return raw.split(LINE_BREAKS).map((l) => l.replace(CONTROL_CHARS2, ""));
28658
28694
  }
28659
28695
  function terminalSafeInline(raw) {
28660
28696
  return terminalSafeLines(raw).join(" ");
@@ -30058,12 +30094,13 @@ async function run() {
30058
30094
  process.exit(1);
30059
30095
  }
30060
30096
  }
30061
- var TERMINALHIRE_DIR11, INDEX_CACHE_FILE2, CLAIM_PUSH_MARKER, REPO_CONTINUITY_NUDGE_MARKER, API_URL, CLAIM_SYNC_BASE2, CLAIM_CONSENT_VERSION, CLAIM_POLL_INTERVAL_MS, CLAIM_POLL_TIMEOUT_MS, GH_API2, GH_HEADERS2, CONTENTION_HINT, AI_DISCLOSURE_NOTE, pExecFile, VALUE_FLAGS, ASSIGNMENT_MARKER, STAKE_MARKER, STANDDOWN_MARKER, OUR_MARKERS, STAKE_POST_TIMEOUT_MS, STAKE_POSTING_GRACE_MS, TAKE_BOT_REPOS, SUBMIT_ACCEPTS, REVISE_RECOVERY_STATES, PUSH_TOKEN_REFUSAL, SYNC_BACKGROUND_PUSH_ACTIVE_FIELD, ISSUE_OUTCOME_TERMINAL, RUNS_POLL_INTERVAL_MS, RUNS_POLL_ATTEMPTS, CLAIM_EVENT_LABEL, LINE_BREAKS, CONTROL_CHARS;
30097
+ var TERMINALHIRE_DIR11, INDEX_CACHE_FILE2, CLAIM_PUSH_MARKER, REPO_CONTINUITY_NUDGE_MARKER, API_URL, CLAIM_SYNC_BASE2, CLAIM_CONSENT_VERSION, CLAIM_POLL_INTERVAL_MS, CLAIM_POLL_TIMEOUT_MS, GH_API2, GH_HEADERS2, CONTENTION_HINT, AI_DISCLOSURE_NOTE, pExecFile, VALUE_FLAGS, ASSIGNMENT_MARKER, STAKE_MARKER, STANDDOWN_MARKER, OUR_MARKERS, STAKE_POST_TIMEOUT_MS, STAKE_POSTING_GRACE_MS, TAKE_BOT_REPOS, SUBMIT_ACCEPTS, REVISE_RECOVERY_STATES, PUSH_TOKEN_REFUSAL, SYNC_BACKGROUND_PUSH_ACTIVE_FIELD, ISSUE_OUTCOME_TERMINAL, RUNS_POLL_INTERVAL_MS, RUNS_POLL_ATTEMPTS, CLAIM_EVENT_LABEL, LINE_BREAKS, CONTROL_CHARS2;
30062
30098
  var init_jpi_claim = __esm({
30063
30099
  "bin/jpi-claim.js"() {
30064
30100
  "use strict";
30065
30101
  init_src();
30066
30102
  init_open_url();
30103
+ init_sanitize();
30067
30104
  init_policy_acks();
30068
30105
  init_claims();
30069
30106
  init_state_dir();
@@ -30126,7 +30163,7 @@ var init_jpi_claim = __esm({
30126
30163
  rejected: "the founder rejected"
30127
30164
  };
30128
30165
  LINE_BREAKS = /\r\n|[\r\n\v\f\u0085\u2028\u2029]/;
30129
- CONTROL_CHARS = /[\u0000-\u001F\u007F-\u009F]/g;
30166
+ CONTROL_CHARS2 = /[\u0000-\u001F\u007F-\u009F]/g;
30130
30167
  }
30131
30168
  });
30132
30169
 
@@ -92,7 +92,7 @@ function render() {
92
92
  const founderOpen = founderOpenCount(entry);
93
93
  const stale = sessionStale(entry) && unread === 0 && incoming === 0;
94
94
  const segments = [];
95
- if (approved > 0) segments.push(`\u2705 ${approved} approved \u2014 run: th claim list`);
95
+ if (approved > 0) segments.push(`\u2705 ${approved} approved \u2014 run: th claim start`);
96
96
  if (founderNeedsYou > 0) {
97
97
  segments.push(
98
98
  `\u{1F9ED} ${founderNeedsYou} claim${founderNeedsYou === 1 ? "" : "s"} await your decision \u2014 run: th bounties`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "terminalhire",
3
- "version": "0.41.0",
3
+ "version": "0.41.1",
4
4
  "description": "Local-first job matching for developers — ambient job matches in the Claude Code spinner. Your profile never leaves your machine.",
5
5
  "repository": {
6
6
  "type": "git",