terminalhire 0.19.0 → 0.19.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.
@@ -182,7 +182,10 @@ var init_config = __esm({
182
182
  inboundNudgeDisclosed: false,
183
183
  contributeEnabled: false,
184
184
  contributePrompted: false,
185
- betaOptIn: false
185
+ betaOptIn: false,
186
+ lastFullFeedbackAt: null,
187
+ lastPulseAskAt: null,
188
+ pulseDisclosed: false
186
189
  };
187
190
  }
188
191
  });
@@ -343,9 +346,9 @@ var init_keytar = __esm({
343
346
  }
344
347
  });
345
348
 
346
- // node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node
349
+ // node-file:/Users/ericgang/job-placement-inline/.claude/worktrees/release-0192/node_modules/keytar/build/Release/keytar.node
347
350
  var require_keytar = __commonJS({
348
- "node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node"(exports, module) {
351
+ "node-file:/Users/ericgang/job-placement-inline/.claude/worktrees/release-0192/node_modules/keytar/build/Release/keytar.node"(exports, module) {
349
352
  "use strict";
350
353
  init_keytar();
351
354
  try {
@@ -7999,12 +8002,12 @@ async function runLogin() {
7999
8002
  Fetching public profile for @${login}...`);
8000
8003
  let ghProfile;
8001
8004
  if (process.env["TERMINALHIRE_GITHUB_MOCK"] === "1" || process.env["JPI_GITHUB_MOCK"] === "1") {
8002
- const { fileURLToPath: fileURLToPath9 } = await import("url");
8003
- const { join: join33 } = await import("path");
8004
- const __dirname8 = fileURLToPath9(new URL(".", import.meta.url));
8005
- const fixturePath = join33(__dirname8, "../../fixtures/github-sample.json");
8006
- const { readFileSync: readFileSync30 } = await import("fs");
8007
- ghProfile = JSON.parse(readFileSync30(fixturePath, "utf8"));
8005
+ const { fileURLToPath: fileURLToPath10 } = await import("url");
8006
+ const { join: join34 } = await import("path");
8007
+ const __dirname9 = fileURLToPath10(new URL(".", import.meta.url));
8008
+ const fixturePath = join34(__dirname9, "../../fixtures/github-sample.json");
8009
+ const { readFileSync: readFileSync31 } = await import("fs");
8010
+ ghProfile = JSON.parse(readFileSync31(fixturePath, "utf8"));
8008
8011
  } else {
8009
8012
  ghProfile = await fetchGitHubProfile2(login, token);
8010
8013
  }
@@ -8321,6 +8324,95 @@ var init_sanitize = __esm({
8321
8324
  }
8322
8325
  });
8323
8326
 
8327
+ // bin/pulse-prompt.js
8328
+ var pulse_prompt_exports = {};
8329
+ __export(pulse_prompt_exports, {
8330
+ maybeAskPulse: () => maybeAskPulse
8331
+ });
8332
+ import { createInterface as createInterface2 } from "readline";
8333
+ import { readFileSync as readFileSync9, existsSync as existsSync7 } from "fs";
8334
+ import { join as join9 } from "path";
8335
+ import { fileURLToPath as fileURLToPath3 } from "url";
8336
+ function readLocalVersion2() {
8337
+ try {
8338
+ for (const p of [join9(__dirname2, "..", "..", "package.json"), join9(__dirname2, "..", "package.json")]) {
8339
+ if (existsSync7(p)) {
8340
+ const pkg = JSON.parse(readFileSync9(p, "utf8"));
8341
+ if (pkg.version) return pkg.version;
8342
+ }
8343
+ }
8344
+ } catch {
8345
+ }
8346
+ return null;
8347
+ }
8348
+ async function maybeAskPulse() {
8349
+ if (!(process.stdout.isTTY && process.stdin.isTTY)) return;
8350
+ const config2 = readConfig();
8351
+ if (config2.betaOptIn !== true) return;
8352
+ const cookie = readWebSessionCookie();
8353
+ if (!cookie) return;
8354
+ const last = config2.lastPulseAskAt;
8355
+ if (last && Date.now() - Date.parse(last) < PULSE_ASK_INTERVAL_MS) return;
8356
+ if (config2.pulseDisclosed !== true) {
8357
+ console.log("");
8358
+ console.log(" \u2726 Heads up: terminalhire will occasionally (max once a day) ask you to");
8359
+ console.log(" rate it 0\u20133. Replying sends ONLY that number + your CLI version/OS;");
8360
+ console.log(" Enter always skips and sends nothing.");
8361
+ writeConfig({ pulseDisclosed: true, lastPulseAskAt: (/* @__PURE__ */ new Date()).toISOString() });
8362
+ return;
8363
+ }
8364
+ writeConfig({ lastPulseAskAt: (/* @__PURE__ */ new Date()).toISOString() });
8365
+ const rl = createInterface2({ input: process.stdin, output: process.stdout });
8366
+ const ask3 = (question) => new Promise((resolve2) => {
8367
+ const onClose = () => resolve2(null);
8368
+ rl.once("close", onClose);
8369
+ rl.question(question, (answer2) => {
8370
+ rl.removeListener("close", onClose);
8371
+ resolve2((answer2 || "").trim());
8372
+ });
8373
+ });
8374
+ const answer = await ask3(
8375
+ " \u2726 Quick pulse \u2014 how's terminalhire? 0\u20133 (Enter skips; a reply sends ONLY the score + CLI version/OS): "
8376
+ );
8377
+ rl.close();
8378
+ if (!/^[0-3]$/.test(answer || "")) {
8379
+ console.log(" (skipped \u2014 nothing sent)");
8380
+ return;
8381
+ }
8382
+ const pulse = Number.parseInt(answer, 10);
8383
+ const cliVersion = readLocalVersion2() || "unknown";
8384
+ const os = process.platform;
8385
+ let res;
8386
+ try {
8387
+ res = await fetch(`${API_BASE}/api/feedback`, {
8388
+ method: "POST",
8389
+ headers: { "Content-Type": "application/json", Cookie: `${GH_SESSION_COOKIE}=${cookie}` },
8390
+ body: JSON.stringify({ category: "pulse", pulse, cliVersion, os }),
8391
+ signal: AbortSignal.timeout(1e4)
8392
+ });
8393
+ } catch {
8394
+ console.log(" (could not send your pulse just now \u2014 no worries)");
8395
+ return;
8396
+ }
8397
+ if (!res.ok) {
8398
+ console.log(" (could not log your pulse right now \u2014 thanks anyway)");
8399
+ return;
8400
+ }
8401
+ console.log(" \u2713 Thanks \u2014 logged.");
8402
+ }
8403
+ var __dirname2, API_BASE, GH_SESSION_COOKIE, PULSE_ASK_INTERVAL_MS;
8404
+ var init_pulse_prompt = __esm({
8405
+ "bin/pulse-prompt.js"() {
8406
+ "use strict";
8407
+ init_web_session();
8408
+ init_config();
8409
+ __dirname2 = fileURLToPath3(new URL(".", import.meta.url));
8410
+ API_BASE = process.env["TERMINALHIRE_API_URL"] || "https://terminalhire.com";
8411
+ GH_SESSION_COOKIE = "__jpi_gh_session";
8412
+ PULSE_ASK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
8413
+ }
8414
+ });
8415
+
8324
8416
  // bin/jpi-jobs.js
8325
8417
  var jpi_jobs_exports = {};
8326
8418
  __export(jpi_jobs_exports, {
@@ -8330,11 +8422,11 @@ __export(jpi_jobs_exports, {
8330
8422
  run: () => run2,
8331
8423
  statusLabel: () => statusLabel
8332
8424
  });
8333
- import { readFileSync as readFileSync9 } from "fs";
8334
- import { join as join9 } from "path";
8425
+ import { readFileSync as readFileSync10 } from "fs";
8426
+ import { join as join10 } from "path";
8335
8427
  import { homedir as homedir8 } from "os";
8336
- import { createInterface as createInterface2 } from "readline";
8337
- import { fileURLToPath as fileURLToPath3 } from "url";
8428
+ import { createInterface as createInterface3 } from "readline";
8429
+ import { fileURLToPath as fileURLToPath4 } from "url";
8338
8430
  function applyStatusView(decorated, filter) {
8339
8431
  if (!filter) return decorated.filter((d) => d.jobStatus?.status !== "dismissed");
8340
8432
  switch (filter) {
@@ -8370,7 +8462,7 @@ function appliedThisWeek(statusMap, now = Date.now()) {
8370
8462
  }
8371
8463
  function readIndexCache() {
8372
8464
  try {
8373
- const raw = readFileSync9(INDEX_CACHE_FILE2, "utf8");
8465
+ const raw = readFileSync10(INDEX_CACHE_FILE2, "utf8");
8374
8466
  const entry = JSON.parse(raw);
8375
8467
  if (Date.now() - entry.ts < INDEX_TTL_MS) return entry.index;
8376
8468
  return null;
@@ -8393,7 +8485,7 @@ async function fetchIndex() {
8393
8485
  return index;
8394
8486
  }
8395
8487
  function prompt(question) {
8396
- const rl = createInterface2({ input: process.stdin, output: process.stdout });
8488
+ const rl = createInterface3({ input: process.stdin, output: process.stdout });
8397
8489
  return new Promise((resolve2) => {
8398
8490
  rl.question(question, (answer) => {
8399
8491
  rl.close();
@@ -8625,34 +8717,38 @@ Enter a number to act on a role, or press Enter to exit: `
8625
8717
  );
8626
8718
  const absIdx = parseInt(pick2, 10) - 1;
8627
8719
  const localIdx = absIdx - (pageInfo.page - 1) * pageInfo.limit;
8628
- if (isNaN(absIdx) || localIdx < 0 || localIdx >= shown.length) {
8629
- return;
8630
- }
8631
- const chosen = shown[localIdx];
8632
- if (chosen.job.applyMode === "direct") {
8633
- markClicked(chosen.job.id);
8634
- console.log(`
8720
+ if (!isNaN(absIdx) && localIdx >= 0 && localIdx < shown.length) {
8721
+ const chosen = shown[localIdx];
8722
+ if (chosen.job.applyMode === "direct") {
8723
+ markClicked(chosen.job.id);
8724
+ console.log(`
8635
8725
  Open this URL to apply directly (no data shared):
8636
8726
  ${sanitizeText(chosen.job.url)}`);
8637
- console.log(` (marked "clicked" locally \u2014 mark it applied with: terminalhire jobs mark ${chosen.job.id} applied)`);
8638
- } else if (chosen.job.applyMode === "buyer-lead") {
8639
- await handleBuyerLead(chosen.job, profile);
8727
+ console.log(` (marked "clicked" locally \u2014 mark it applied with: terminalhire jobs mark ${chosen.job.id} applied)`);
8728
+ } else if (chosen.job.applyMode === "buyer-lead") {
8729
+ await handleBuyerLead(chosen.job, profile);
8730
+ }
8731
+ }
8732
+ try {
8733
+ const { maybeAskPulse: maybeAskPulse2 } = await Promise.resolve().then(() => (init_pulse_prompt(), pulse_prompt_exports));
8734
+ await maybeAskPulse2();
8735
+ } catch {
8640
8736
  }
8641
8737
  } catch (err) {
8642
8738
  console.error("terminalhire jobs error:", err.message ?? err);
8643
8739
  process.exit(1);
8644
8740
  }
8645
8741
  }
8646
- var __dirname2, TERMINALHIRE_DIR6, INDEX_CACHE_FILE2, INDEX_TTL_MS, API_URL, DEFAULT_LIMIT, args, limitArg, LIMIT, REMOTE_ONLY, SHOW_ALL, pageArg, PAGE, statusArg, STATUS_FILTER, VALID_STATUS_FILTERS;
8742
+ var __dirname3, TERMINALHIRE_DIR6, INDEX_CACHE_FILE2, INDEX_TTL_MS, API_URL, DEFAULT_LIMIT, args, limitArg, LIMIT, REMOTE_ONLY, SHOW_ALL, pageArg, PAGE, statusArg, STATUS_FILTER, VALID_STATUS_FILTERS;
8647
8743
  var init_jpi_jobs = __esm({
8648
8744
  "bin/jpi-jobs.js"() {
8649
8745
  "use strict";
8650
8746
  init_job_status_store();
8651
8747
  init_cache_store();
8652
8748
  init_sanitize();
8653
- __dirname2 = fileURLToPath3(new URL(".", import.meta.url));
8654
- TERMINALHIRE_DIR6 = process.env.TERMINALHIRE_DIR || join9(homedir8(), ".terminalhire");
8655
- INDEX_CACHE_FILE2 = join9(TERMINALHIRE_DIR6, "index-cache.json");
8749
+ __dirname3 = fileURLToPath4(new URL(".", import.meta.url));
8750
+ TERMINALHIRE_DIR6 = process.env.TERMINALHIRE_DIR || join10(homedir8(), ".terminalhire");
8751
+ INDEX_CACHE_FILE2 = join10(TERMINALHIRE_DIR6, "index-cache.json");
8656
8752
  INDEX_TTL_MS = 15 * 60 * 1e3;
8657
8753
  API_URL = process.env["TERMINALHIRE_API_URL"] ?? process.env["JPI_API_URL"] ?? "https://terminalhire.com";
8658
8754
  DEFAULT_LIMIT = 10;
@@ -8670,12 +8766,12 @@ var init_jpi_jobs = __esm({
8670
8766
  });
8671
8767
 
8672
8768
  // bin/directory.js
8673
- import { readFileSync as readFileSync10, writeFileSync as writeFileSync8, mkdirSync as mkdirSync8 } from "fs";
8674
- import { join as join10 } from "path";
8769
+ import { readFileSync as readFileSync11, writeFileSync as writeFileSync8, mkdirSync as mkdirSync8 } from "fs";
8770
+ import { join as join11 } from "path";
8675
8771
  import { homedir as homedir9 } from "os";
8676
8772
  function readDirectoryCache() {
8677
8773
  try {
8678
- const entry = JSON.parse(readFileSync10(DIRECTORY_CACHE_FILE, "utf8"));
8774
+ const entry = JSON.parse(readFileSync11(DIRECTORY_CACHE_FILE, "utf8"));
8679
8775
  if (typeof entry.ts === "number" && Number.isFinite(entry.ts) && Date.now() - entry.ts < INDEX_TTL_MS2) {
8680
8776
  return { index: entry.index, ts: entry.ts };
8681
8777
  }
@@ -8690,7 +8786,7 @@ function writeDirectoryCache(index) {
8690
8786
  }
8691
8787
  function readProject() {
8692
8788
  try {
8693
- return JSON.parse(readFileSync10(PROJECT_FILE, "utf8"));
8789
+ return JSON.parse(readFileSync11(PROJECT_FILE, "utf8"));
8694
8790
  } catch {
8695
8791
  return null;
8696
8792
  }
@@ -8747,9 +8843,9 @@ var TERMINALHIRE_DIR7, DIRECTORY_CACHE_FILE, PROJECT_FILE, INDEX_TTL_MS2, API_UR
8747
8843
  var init_directory2 = __esm({
8748
8844
  "bin/directory.js"() {
8749
8845
  "use strict";
8750
- TERMINALHIRE_DIR7 = process.env.TERMINALHIRE_DIR || join10(homedir9(), ".terminalhire");
8751
- DIRECTORY_CACHE_FILE = join10(TERMINALHIRE_DIR7, "directory-cache.json");
8752
- PROJECT_FILE = join10(TERMINALHIRE_DIR7, "project.json");
8846
+ TERMINALHIRE_DIR7 = process.env.TERMINALHIRE_DIR || join11(homedir9(), ".terminalhire");
8847
+ DIRECTORY_CACHE_FILE = join11(TERMINALHIRE_DIR7, "directory-cache.json");
8848
+ PROJECT_FILE = join11(TERMINALHIRE_DIR7, "project.json");
8753
8849
  INDEX_TTL_MS2 = 15 * 60 * 1e3;
8754
8850
  API_URL2 = process.env["TERMINALHIRE_API_URL"] ?? process.env["JPI_API_URL"] ?? "https://terminalhire.com";
8755
8851
  }
@@ -8761,9 +8857,9 @@ __export(jpi_devs_exports, {
8761
8857
  reportMatched: () => reportMatched,
8762
8858
  run: () => run3
8763
8859
  });
8764
- import { createInterface as createInterface3 } from "readline";
8860
+ import { createInterface as createInterface4 } from "readline";
8765
8861
  function prompt2(question) {
8766
- const rl = createInterface3({ input: process.stdin, output: process.stdout });
8862
+ const rl = createInterface4({ input: process.stdin, output: process.stdout });
8767
8863
  return new Promise((resolve2) => {
8768
8864
  rl.question(question, (answer) => {
8769
8865
  rl.close();
@@ -8880,19 +8976,19 @@ var jpi_project_exports = {};
8880
8976
  __export(jpi_project_exports, {
8881
8977
  run: () => run4
8882
8978
  });
8883
- import { readFileSync as readFileSync11, writeFileSync as writeFileSync9, mkdirSync as mkdirSync9 } from "fs";
8884
- import { join as join11 } from "path";
8979
+ import { readFileSync as readFileSync12, writeFileSync as writeFileSync9, mkdirSync as mkdirSync9 } from "fs";
8980
+ import { join as join12 } from "path";
8885
8981
  import { homedir as homedir10 } from "os";
8886
- import { createInterface as createInterface4 } from "readline";
8982
+ import { createInterface as createInterface5 } from "readline";
8887
8983
  function readProject2() {
8888
8984
  try {
8889
- return JSON.parse(readFileSync11(PROJECT_FILE2, "utf8"));
8985
+ return JSON.parse(readFileSync12(PROJECT_FILE2, "utf8"));
8890
8986
  } catch {
8891
8987
  return null;
8892
8988
  }
8893
8989
  }
8894
8990
  function promptRaw(question) {
8895
- const rl = createInterface4({ input: process.stdin, output: process.stdout });
8991
+ const rl = createInterface5({ input: process.stdin, output: process.stdout });
8896
8992
  return new Promise((resolve2) => {
8897
8993
  rl.question(question, (answer) => {
8898
8994
  rl.close();
@@ -8978,8 +9074,8 @@ var TERMINALHIRE_DIR8, PROJECT_FILE2, args3, SHOW, declarationArg;
8978
9074
  var init_jpi_project = __esm({
8979
9075
  "bin/jpi-project.js"() {
8980
9076
  "use strict";
8981
- TERMINALHIRE_DIR8 = process.env.TERMINALHIRE_DIR || join11(homedir10(), ".terminalhire");
8982
- PROJECT_FILE2 = join11(TERMINALHIRE_DIR8, "project.json");
9077
+ TERMINALHIRE_DIR8 = process.env.TERMINALHIRE_DIR || join12(homedir10(), ".terminalhire");
9078
+ PROJECT_FILE2 = join12(TERMINALHIRE_DIR8, "project.json");
8983
9079
  args3 = process.argv.slice(2);
8984
9080
  SHOW = args3.includes("--show");
8985
9081
  declarationArg = args3.filter((a) => !a.startsWith("--")).join(" ").trim();
@@ -8991,13 +9087,13 @@ var jpi_bounties_exports = {};
8991
9087
  __export(jpi_bounties_exports, {
8992
9088
  run: () => run5
8993
9089
  });
8994
- import { readFileSync as readFileSync12 } from "fs";
8995
- import { join as join12 } from "path";
9090
+ import { readFileSync as readFileSync13 } from "fs";
9091
+ import { join as join13 } from "path";
8996
9092
  import { homedir as homedir11 } from "os";
8997
- import { createInterface as createInterface5 } from "readline";
9093
+ import { createInterface as createInterface6 } from "readline";
8998
9094
  function readIndexCache2() {
8999
9095
  try {
9000
- const entry = JSON.parse(readFileSync12(INDEX_CACHE_FILE3, "utf8"));
9096
+ const entry = JSON.parse(readFileSync13(INDEX_CACHE_FILE3, "utf8"));
9001
9097
  if (Date.now() - entry.ts < INDEX_TTL_MS3) return entry.index;
9002
9098
  return null;
9003
9099
  } catch {
@@ -9017,7 +9113,7 @@ async function fetchIndex2() {
9017
9113
  return index;
9018
9114
  }
9019
9115
  function prompt3(question) {
9020
- const rl = createInterface5({ input: process.stdin, output: process.stdout });
9116
+ const rl = createInterface6({ input: process.stdin, output: process.stdout });
9021
9117
  return new Promise((resolve2) => {
9022
9118
  rl.question(question, (answer) => {
9023
9119
  rl.close();
@@ -9112,8 +9208,8 @@ var init_jpi_bounties = __esm({
9112
9208
  init_src();
9113
9209
  init_cache_store();
9114
9210
  init_sanitize();
9115
- TERMINALHIRE_DIR9 = process.env.TERMINALHIRE_DIR || join12(homedir11(), ".terminalhire");
9116
- INDEX_CACHE_FILE3 = join12(TERMINALHIRE_DIR9, "index-cache.json");
9211
+ TERMINALHIRE_DIR9 = process.env.TERMINALHIRE_DIR || join13(homedir11(), ".terminalhire");
9212
+ INDEX_CACHE_FILE3 = join13(TERMINALHIRE_DIR9, "index-cache.json");
9117
9213
  INDEX_TTL_MS3 = 15 * 60 * 1e3;
9118
9214
  API_URL4 = process.env["TERMINALHIRE_API_URL"] ?? process.env["JPI_API_URL"] ?? "https://terminalhire.com";
9119
9215
  DEFAULT_LIMIT3 = 15;
@@ -9134,13 +9230,13 @@ __export(jpi_contribute_exports, {
9134
9230
  renderRow: () => renderRow,
9135
9231
  run: () => run6
9136
9232
  });
9137
- import { readFileSync as readFileSync13 } from "fs";
9138
- import { join as join13 } from "path";
9233
+ import { readFileSync as readFileSync14 } from "fs";
9234
+ import { join as join14 } from "path";
9139
9235
  import { homedir as homedir12 } from "os";
9140
- import { createInterface as createInterface6 } from "readline";
9236
+ import { createInterface as createInterface7 } from "readline";
9141
9237
  function readIndexCache3() {
9142
9238
  try {
9143
- const entry = JSON.parse(readFileSync13(INDEX_CACHE_FILE4, "utf8"));
9239
+ const entry = JSON.parse(readFileSync14(INDEX_CACHE_FILE4, "utf8"));
9144
9240
  if (Date.now() - entry.ts < INDEX_TTL_MS4) return entry.index;
9145
9241
  return null;
9146
9242
  } catch {
@@ -9162,7 +9258,7 @@ async function fetchIndex3(fetchImpl, useCache = true) {
9162
9258
  return index;
9163
9259
  }
9164
9260
  function defaultPrompt(question) {
9165
- const rl = createInterface6({ input: process.stdin, output: process.stdout });
9261
+ const rl = createInterface7({ input: process.stdin, output: process.stdout });
9166
9262
  return new Promise((resolve2) => {
9167
9263
  rl.question(question, (answer) => {
9168
9264
  rl.close();
@@ -9251,8 +9347,8 @@ var init_jpi_contribute = __esm({
9251
9347
  init_cache_store();
9252
9348
  init_config();
9253
9349
  init_sanitize();
9254
- TERMINALHIRE_DIR10 = process.env.TERMINALHIRE_DIR || join13(homedir12(), ".terminalhire");
9255
- INDEX_CACHE_FILE4 = join13(TERMINALHIRE_DIR10, "index-cache.json");
9350
+ TERMINALHIRE_DIR10 = process.env.TERMINALHIRE_DIR || join14(homedir12(), ".terminalhire");
9351
+ INDEX_CACHE_FILE4 = join14(TERMINALHIRE_DIR10, "index-cache.json");
9256
9352
  INDEX_TTL_MS4 = 15 * 60 * 1e3;
9257
9353
  API_URL5 = process.env["TERMINALHIRE_API_URL"] ?? process.env["JPI_API_URL"] ?? "https://terminalhire.com";
9258
9354
  HEADER = "Contribution opportunities \u2014 open issues where a merged PR actually counts toward your r\xE9sum\xE9.\nRepos \u226550\u2605 / \u226510 contributors \xB7 unassigned \xB7 merit-merge \xB7 matched locally to your stack.";
@@ -9311,8 +9407,8 @@ __export(claims_exports, {
9311
9407
  toPushedClaim: () => toPushedClaim,
9312
9408
  updateClaim: () => updateClaim
9313
9409
  });
9314
- import { readFileSync as readFileSync14, writeFileSync as writeFileSync10, mkdirSync as mkdirSync10, renameSync as renameSync3, existsSync as existsSync7 } from "fs";
9315
- import { join as join14 } from "path";
9410
+ import { readFileSync as readFileSync15, writeFileSync as writeFileSync10, mkdirSync as mkdirSync10, renameSync as renameSync3, existsSync as existsSync8 } from "fs";
9411
+ import { join as join15 } from "path";
9316
9412
  import { homedir as homedir13 } from "os";
9317
9413
  function toPushedClaim(claim) {
9318
9414
  return {
@@ -9333,8 +9429,8 @@ function normalizeClaim(c) {
9333
9429
  }
9334
9430
  function readClaims() {
9335
9431
  try {
9336
- if (!existsSync7(CLAIMS_FILE)) return [];
9337
- const data = JSON.parse(readFileSync14(CLAIMS_FILE, "utf8"));
9432
+ if (!existsSync8(CLAIMS_FILE)) return [];
9433
+ const data = JSON.parse(readFileSync15(CLAIMS_FILE, "utf8"));
9338
9434
  const claims = Array.isArray(data?.claims) ? data.claims : [];
9339
9435
  return claims.map(normalizeClaim);
9340
9436
  } catch {
@@ -9406,8 +9502,8 @@ var TERMINALHIRE_DIR11, CLAIMS_FILE, TERMINAL_STATES;
9406
9502
  var init_claims = __esm({
9407
9503
  "src/claims.ts"() {
9408
9504
  "use strict";
9409
- TERMINALHIRE_DIR11 = join14(homedir13(), ".terminalhire");
9410
- CLAIMS_FILE = join14(TERMINALHIRE_DIR11, "claims.json");
9505
+ TERMINALHIRE_DIR11 = join15(homedir13(), ".terminalhire");
9506
+ CLAIMS_FILE = join15(TERMINALHIRE_DIR11, "claims.json");
9411
9507
  TERMINAL_STATES = /* @__PURE__ */ new Set(["merged", "abandoned"]);
9412
9508
  }
9413
9509
  });
@@ -9510,12 +9606,12 @@ __export(jpi_claim_exports, {
9510
9606
  resolveBounty: () => resolveBounty,
9511
9607
  run: () => run7
9512
9608
  });
9513
- import { readFileSync as readFileSync15, writeFileSync as writeFileSync11, mkdirSync as mkdirSync11, existsSync as existsSync8, rmSync as rmSync3 } from "fs";
9514
- import { join as join15 } from "path";
9609
+ import { readFileSync as readFileSync16, writeFileSync as writeFileSync11, mkdirSync as mkdirSync11, existsSync as existsSync9, rmSync as rmSync3 } from "fs";
9610
+ import { join as join16 } from "path";
9515
9611
  import { homedir as homedir14, hostname as osHostname } from "os";
9516
9612
  import { execFile } from "child_process";
9517
9613
  import { promisify } from "util";
9518
- import { createInterface as createInterface7 } from "readline";
9614
+ import { createInterface as createInterface8 } from "readline";
9519
9615
  function buildSubmitBody(issueNumber) {
9520
9616
  const closesLine = issueNumber ? `Closes #${issueNumber}
9521
9617
 
@@ -9540,7 +9636,7 @@ async function sh(cmd, args5, opts = {}) {
9540
9636
  return String(stdout).trim();
9541
9637
  }
9542
9638
  async function confirm(question) {
9543
- const rl = createInterface7({ input: process.stdin, output: process.stdout });
9639
+ const rl = createInterface8({ input: process.stdin, output: process.stdout });
9544
9640
  try {
9545
9641
  const ans = await new Promise((resolve2) => rl.question(question, resolve2));
9546
9642
  return /^y(es)?$/i.test(String(ans).trim());
@@ -9577,8 +9673,8 @@ function parseRepoFromRemote(url) {
9577
9673
  return m ? `${m[1]}/${m[2]}` : null;
9578
9674
  }
9579
9675
  function readClaimablePool() {
9580
- if (!existsSync8(INDEX_CACHE_FILE5)) return [];
9581
- const entry = JSON.parse(readFileSync15(INDEX_CACHE_FILE5, "utf8"));
9676
+ if (!existsSync9(INDEX_CACHE_FILE5)) return [];
9677
+ const entry = JSON.parse(readFileSync16(INDEX_CACHE_FILE5, "utf8"));
9582
9678
  const bounties = (entry?.index?.jobs ?? []).filter((j) => j.source === "bounty");
9583
9679
  const contributions = (entry?.index?.contribute ?? []).filter((j) => j.source === "contribute");
9584
9680
  return [...bounties, ...contributions];
@@ -10228,7 +10324,7 @@ async function cmdSubmit(id, worktreeOverride) {
10228
10324
  console.log(` Run 'terminalhire claim status ${id}' after the maintainer acts to fold the merge into your accepted-PR rate.`);
10229
10325
  }
10230
10326
  function askYes(question) {
10231
- const rl = createInterface7({ input: process.stdin, output: process.stdout });
10327
+ const rl = createInterface8({ input: process.stdin, output: process.stdout });
10232
10328
  return new Promise((res) => rl.question(question, (a) => {
10233
10329
  rl.close();
10234
10330
  res(String(a).trim().toLowerCase());
@@ -10239,7 +10335,7 @@ function claimSleep(ms) {
10239
10335
  }
10240
10336
  function readClaimPushMarker() {
10241
10337
  try {
10242
- return existsSync8(CLAIM_PUSH_MARKER) ? JSON.parse(readFileSync15(CLAIM_PUSH_MARKER, "utf8")) : null;
10338
+ return existsSync9(CLAIM_PUSH_MARKER) ? JSON.parse(readFileSync16(CLAIM_PUSH_MARKER, "utf8")) : null;
10243
10339
  } catch {
10244
10340
  return null;
10245
10341
  }
@@ -10484,9 +10580,9 @@ var init_jpi_claim = __esm({
10484
10580
  "use strict";
10485
10581
  init_src();
10486
10582
  init_open_url();
10487
- TERMINALHIRE_DIR12 = process.env.TERMINALHIRE_DIR || join15(homedir14(), ".terminalhire");
10488
- INDEX_CACHE_FILE5 = join15(TERMINALHIRE_DIR12, "index-cache.json");
10489
- CLAIM_PUSH_MARKER = join15(TERMINALHIRE_DIR12, "claim-push.json");
10583
+ TERMINALHIRE_DIR12 = process.env.TERMINALHIRE_DIR || join16(homedir14(), ".terminalhire");
10584
+ INDEX_CACHE_FILE5 = join16(TERMINALHIRE_DIR12, "index-cache.json");
10585
+ CLAIM_PUSH_MARKER = join16(TERMINALHIRE_DIR12, "claim-push.json");
10490
10586
  API_URL6 = process.env["TERMINALHIRE_API_URL"] ?? process.env["JPI_API_URL"] ?? "https://terminalhire.com";
10491
10587
  CLAIM_SYNC_BASE = "https://terminalhire.com";
10492
10588
  CLAIM_CONSENT_VERSION = 1;
@@ -10661,7 +10757,7 @@ function finalize(build) {
10661
10757
  };
10662
10758
  }
10663
10759
  function reconstruct(files, opts = {}) {
10664
- const join33 = opts.joinSidechains !== false;
10760
+ const join34 = opts.joinSidechains !== false;
10665
10761
  const mains = [];
10666
10762
  const sidechains = [];
10667
10763
  for (const file of files) {
@@ -10686,7 +10782,7 @@ function reconstruct(files, opts = {}) {
10686
10782
  }
10687
10783
  const orphanedSidechainPaths = [];
10688
10784
  const joinedPaths = /* @__PURE__ */ new Set();
10689
- if (join33) {
10785
+ if (join34) {
10690
10786
  const sidechainsBySession = /* @__PURE__ */ new Map();
10691
10787
  for (const sc of sidechains) {
10692
10788
  const acc = sidechainsBySession.get(sc.sessionId) ?? [];
@@ -11023,14 +11119,14 @@ __export(trajectory_exports, {
11023
11119
  runTrajectoryPush: () => runTrajectoryPush
11024
11120
  });
11025
11121
  import {
11026
- existsSync as existsSync9,
11122
+ existsSync as existsSync10,
11027
11123
  mkdirSync as mkdirSync12,
11028
- readFileSync as readFileSync16,
11124
+ readFileSync as readFileSync17,
11029
11125
  readdirSync,
11030
11126
  writeFileSync as writeFileSync12
11031
11127
  } from "fs";
11032
11128
  import { homedir as homedir15 } from "os";
11033
- import { join as join16 } from "path";
11129
+ import { join as join17 } from "path";
11034
11130
  function isRecord4(value) {
11035
11131
  return typeof value === "object" && value !== null && !Array.isArray(value);
11036
11132
  }
@@ -11062,7 +11158,7 @@ function findJsonlFiles(dir) {
11062
11158
  return out;
11063
11159
  }
11064
11160
  for (const entry of entries) {
11065
- const full = join16(dir, entry.name);
11161
+ const full = join17(dir, entry.name);
11066
11162
  if (entry.isDirectory()) {
11067
11163
  out.push(...findJsonlFiles(full));
11068
11164
  } else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
@@ -11076,7 +11172,7 @@ function loadCorpus(paths) {
11076
11172
  for (const path of paths) {
11077
11173
  let text;
11078
11174
  try {
11079
- text = readFileSync16(path, "utf8");
11175
+ text = readFileSync17(path, "utf8");
11080
11176
  } catch {
11081
11177
  continue;
11082
11178
  }
@@ -11169,10 +11265,10 @@ function renderMarkdown(view) {
11169
11265
  return lines.join("\n");
11170
11266
  }
11171
11267
  function writeExportArtifacts(score, markdown) {
11172
- const dir = join16(homedir15(), ".terminalhire");
11268
+ const dir = join17(homedir15(), ".terminalhire");
11173
11269
  mkdirSync12(dir, { recursive: true });
11174
- const jsonPath = join16(dir, "trajectory-export.json");
11175
- const mdPath = join16(dir, "trajectory-export.md");
11270
+ const jsonPath = join17(dir, "trajectory-export.json");
11271
+ const mdPath = join17(dir, "trajectory-export.md");
11176
11272
  writeFileSync12(jsonPath, JSON.stringify(score, null, 2) + "\n", "utf8");
11177
11273
  writeFileSync12(mdPath, markdown, "utf8");
11178
11274
  return { jsonPath, mdPath };
@@ -11193,8 +11289,8 @@ function renderInward(allNodes, view, files) {
11193
11289
  console.log("");
11194
11290
  }
11195
11291
  function buildTrajectory() {
11196
- const projectsDir = join16(homedir15(), ".claude", "projects");
11197
- if (!existsSync9(projectsDir)) return null;
11292
+ const projectsDir = join17(homedir15(), ".claude", "projects");
11293
+ if (!existsSync10(projectsDir)) return null;
11198
11294
  const paths = findJsonlFiles(projectsDir);
11199
11295
  if (paths.length === 0) return null;
11200
11296
  const files = loadCorpus(paths);
@@ -11267,8 +11363,8 @@ function defaultPushDeps() {
11267
11363
  }
11268
11364
  },
11269
11365
  prompt: async (question) => {
11270
- const { createInterface: createInterface15 } = await import("readline");
11271
- const rl = createInterface15({ input: process.stdin, output: process.stdout });
11366
+ const { createInterface: createInterface16 } = await import("readline");
11367
+ const rl = createInterface16({ input: process.stdin, output: process.stdout });
11272
11368
  return new Promise((res) => {
11273
11369
  rl.question(question, (answer) => {
11274
11370
  rl.close();
@@ -11347,7 +11443,7 @@ async function runTrajectoryPush(opts, overrides) {
11347
11443
  try {
11348
11444
  res2 = await deps.fetchImpl(`${LINK_BASE}/api/trajectory-sync`, {
11349
11445
  method: "DELETE",
11350
- headers: { Cookie: `${GH_SESSION_COOKIE}=${cookie}` },
11446
+ headers: { Cookie: `${GH_SESSION_COOKIE2}=${cookie}` },
11351
11447
  signal: AbortSignal.timeout(1e4)
11352
11448
  });
11353
11449
  } catch (err) {
@@ -11407,7 +11503,7 @@ async function runTrajectoryPush(opts, overrides) {
11407
11503
  try {
11408
11504
  res = await deps.fetchImpl(`${LINK_BASE}/api/trajectory-sync`, {
11409
11505
  method: "POST",
11410
- headers: { "Content-Type": "application/json", Cookie: `${GH_SESSION_COOKIE}=${cookie}` },
11506
+ headers: { "Content-Type": "application/json", Cookie: `${GH_SESSION_COOKIE2}=${cookie}` },
11411
11507
  body: serialized,
11412
11508
  signal: AbortSignal.timeout(1e4)
11413
11509
  });
@@ -11437,7 +11533,7 @@ async function runTrajectoryPush(opts, overrides) {
11437
11533
  deps.log(` \u2192 ${LINK_BASE}/dashboard
11438
11534
  `);
11439
11535
  }
11440
- var prettySignal, LINK_BASE, OAUTH_BASE2, GH_SESSION_COOKIE, PUSH_DENYLIST;
11536
+ var prettySignal, LINK_BASE, OAUTH_BASE2, GH_SESSION_COOKIE2, PUSH_DENYLIST;
11441
11537
  var init_trajectory = __esm({
11442
11538
  "src/trajectory.ts"() {
11443
11539
  "use strict";
@@ -11447,7 +11543,7 @@ var init_trajectory = __esm({
11447
11543
  prettySignal = signalLabel;
11448
11544
  LINK_BASE = process.env["TERMINALHIRE_API_URL"] || "https://terminalhire.com";
11449
11545
  OAUTH_BASE2 = "https://terminalhire.com";
11450
- GH_SESSION_COOKIE = "__jpi_gh_session";
11546
+ GH_SESSION_COOKIE2 = "__jpi_gh_session";
11451
11547
  PUSH_DENYLIST = ["rework", "recovery", "within_session", "fatigue", "vector", "mcp__"];
11452
11548
  }
11453
11549
  });
@@ -11509,8 +11605,8 @@ function defaultIntroDeps() {
11509
11605
  }
11510
11606
  },
11511
11607
  prompt: async (question) => {
11512
- const { createInterface: createInterface15 } = await import("readline");
11513
- const rl = createInterface15({ input: process.stdin, output: process.stdout });
11608
+ const { createInterface: createInterface16 } = await import("readline");
11609
+ const rl = createInterface16({ input: process.stdin, output: process.stdout });
11514
11610
  return new Promise((res) => {
11515
11611
  rl.question(question, (answer) => {
11516
11612
  rl.close();
@@ -11600,7 +11696,7 @@ async function runIntroRequest(args5, overrides) {
11600
11696
  try {
11601
11697
  res = await deps.fetchImpl(`${LINK_BASE2}/api/intro/request`, {
11602
11698
  method: "POST",
11603
- headers: { "Content-Type": "application/json", Cookie: `${GH_SESSION_COOKIE2}=${cookie}` },
11699
+ headers: { "Content-Type": "application/json", Cookie: `${GH_SESSION_COOKIE3}=${cookie}` },
11604
11700
  body: JSON.stringify(payload),
11605
11701
  signal: AbortSignal.timeout(1e4)
11606
11702
  });
@@ -11670,7 +11766,7 @@ async function runIntroRequest(args5, overrides) {
11670
11766
  async function fetchIntros(deps, cookie) {
11671
11767
  const res = await deps.fetchImpl(`${LINK_BASE2}/api/intro/list`, {
11672
11768
  method: "GET",
11673
- headers: { Cookie: `${GH_SESSION_COOKIE2}=${cookie}` },
11769
+ headers: { Cookie: `${GH_SESSION_COOKIE3}=${cookie}` },
11674
11770
  signal: AbortSignal.timeout(1e4)
11675
11771
  });
11676
11772
  if (!res.ok) throw new Error(`/api/intro/list returned ${res.status}`);
@@ -11750,7 +11846,7 @@ async function runIntroDecision(args5, overrides) {
11750
11846
  try {
11751
11847
  res = await deps.fetchImpl(`${LINK_BASE2}/api/intro/accept`, {
11752
11848
  method: "POST",
11753
- headers: { "Content-Type": "application/json", Cookie: `${GH_SESSION_COOKIE2}=${cookie}` },
11849
+ headers: { "Content-Type": "application/json", Cookie: `${GH_SESSION_COOKIE3}=${cookie}` },
11754
11850
  body: JSON.stringify(body),
11755
11851
  signal: AbortSignal.timeout(1e4)
11756
11852
  });
@@ -11813,7 +11909,7 @@ async function runIntroList(overrides) {
11813
11909
  try {
11814
11910
  res = await deps.fetchImpl(`${LINK_BASE2}/api/intro/list`, {
11815
11911
  method: "GET",
11816
- headers: { Cookie: `${GH_SESSION_COOKIE2}=${cookie}` },
11912
+ headers: { Cookie: `${GH_SESSION_COOKIE3}=${cookie}` },
11817
11913
  signal: AbortSignal.timeout(1e4)
11818
11914
  });
11819
11915
  } catch (err) {
@@ -11858,14 +11954,14 @@ async function runIntroList(overrides) {
11858
11954
  }
11859
11955
  deps.log("");
11860
11956
  }
11861
- var LINK_BASE2, GH_SESSION_COOKIE2, UUID_RE;
11957
+ var LINK_BASE2, GH_SESSION_COOKIE3, UUID_RE;
11862
11958
  var init_intro2 = __esm({
11863
11959
  "src/intro.ts"() {
11864
11960
  "use strict";
11865
11961
  init_src();
11866
11962
  init_web_session();
11867
11963
  LINK_BASE2 = process.env["TERMINALHIRE_API_URL"] || "https://terminalhire.com";
11868
- GH_SESSION_COOKIE2 = "__jpi_gh_session";
11964
+ GH_SESSION_COOKIE3 = "__jpi_gh_session";
11869
11965
  UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
11870
11966
  }
11871
11967
  });
@@ -11921,13 +12017,13 @@ var init_jpi_intro = __esm({
11921
12017
  });
11922
12018
 
11923
12019
  // src/chat-keystore.ts
11924
- import { existsSync as existsSync10, mkdirSync as mkdirSync13, readFileSync as readFileSync17, writeFileSync as writeFileSync13, rmSync as rmSync4 } from "fs";
12020
+ import { existsSync as existsSync11, mkdirSync as mkdirSync13, readFileSync as readFileSync18, writeFileSync as writeFileSync13, rmSync as rmSync4 } from "fs";
11925
12021
  import { homedir as homedir16 } from "os";
11926
- import { join as join17 } from "path";
12022
+ import { join as join18 } from "path";
11927
12023
  async function loadOrCreateIdentity() {
11928
12024
  const key = await loadKey();
11929
- if (existsSync10(IDENTITY_FILE)) {
11930
- const blob2 = JSON.parse(readFileSync17(IDENTITY_FILE, "utf8"));
12025
+ if (existsSync11(IDENTITY_FILE)) {
12026
+ const blob2 = JSON.parse(readFileSync18(IDENTITY_FILE, "utf8"));
11931
12027
  return JSON.parse(decrypt(blob2, key));
11932
12028
  }
11933
12029
  const keypair = generateIdentityKeypair();
@@ -11942,19 +12038,19 @@ var init_chat_keystore = __esm({
11942
12038
  "use strict";
11943
12039
  init_src();
11944
12040
  init_github_auth();
11945
- TERMINALHIRE_DIR13 = join17(homedir16(), ".terminalhire");
11946
- IDENTITY_FILE = join17(TERMINALHIRE_DIR13, "chat-identity.enc");
12041
+ TERMINALHIRE_DIR13 = join18(homedir16(), ".terminalhire");
12042
+ IDENTITY_FILE = join18(TERMINALHIRE_DIR13, "chat-identity.enc");
11947
12043
  }
11948
12044
  });
11949
12045
 
11950
12046
  // src/chat-client.ts
11951
- import { existsSync as existsSync11, mkdirSync as mkdirSync14, readFileSync as readFileSync18, writeFileSync as writeFileSync14 } from "fs";
12047
+ import { existsSync as existsSync12, mkdirSync as mkdirSync14, readFileSync as readFileSync19, writeFileSync as writeFileSync14 } from "fs";
11952
12048
  import { homedir as homedir17 } from "os";
11953
- import { join as join18 } from "path";
12049
+ import { join as join19 } from "path";
11954
12050
  function defaultReadPeerPins() {
11955
12051
  try {
11956
- if (!existsSync11(PEERS_FILE)) return {};
11957
- const parsed = JSON.parse(readFileSync18(PEERS_FILE, "utf8"));
12052
+ if (!existsSync12(PEERS_FILE)) return {};
12053
+ const parsed = JSON.parse(readFileSync19(PEERS_FILE, "utf8"));
11958
12054
  if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return {};
11959
12055
  const out = {};
11960
12056
  for (const [login, key] of Object.entries(parsed)) {
@@ -11991,7 +12087,7 @@ function createChatClient(overrides) {
11991
12087
  const cookie = requireCookie();
11992
12088
  const headers = {
11993
12089
  ...init.headers ?? {},
11994
- Cookie: `${GH_SESSION_COOKIE3}=${cookie}`
12090
+ Cookie: `${GH_SESSION_COOKIE4}=${cookie}`
11995
12091
  };
11996
12092
  const res = await deps.fetchImpl(`${CHAT_BASE}${path}`, {
11997
12093
  ...init,
@@ -12136,7 +12232,7 @@ function createChatClient(overrides) {
12136
12232
  getSafetyNumber
12137
12233
  };
12138
12234
  }
12139
- var CHAT_BASE, GH_SESSION_COOKIE3, TERMINALHIRE_DIR14, PEERS_FILE, REQUEST_TIMEOUT_MS, ChatNotLinkedError, ChatSessionExpiredError, SafetyNumberChangedError, ChatRequestError;
12235
+ var CHAT_BASE, GH_SESSION_COOKIE4, TERMINALHIRE_DIR14, PEERS_FILE, REQUEST_TIMEOUT_MS, ChatNotLinkedError, ChatSessionExpiredError, SafetyNumberChangedError, ChatRequestError;
12140
12236
  var init_chat_client = __esm({
12141
12237
  "src/chat-client.ts"() {
12142
12238
  "use strict";
@@ -12144,9 +12240,9 @@ var init_chat_client = __esm({
12144
12240
  init_chat_keystore();
12145
12241
  init_web_session();
12146
12242
  CHAT_BASE = process.env["TERMINALHIRE_API_URL"] || "https://terminalhire.com";
12147
- GH_SESSION_COOKIE3 = "__jpi_gh_session";
12148
- TERMINALHIRE_DIR14 = join18(homedir17(), ".terminalhire");
12149
- PEERS_FILE = join18(TERMINALHIRE_DIR14, "chat-peers.json");
12243
+ GH_SESSION_COOKIE4 = "__jpi_gh_session";
12244
+ TERMINALHIRE_DIR14 = join19(homedir17(), ".terminalhire");
12245
+ PEERS_FILE = join19(TERMINALHIRE_DIR14, "chat-peers.json");
12150
12246
  REQUEST_TIMEOUT_MS = 1e4;
12151
12247
  ChatNotLinkedError = class extends Error {
12152
12248
  constructor() {
@@ -12203,19 +12299,19 @@ __export(jpi_chat_read_exports, {
12203
12299
  syncUnreadBadge: () => syncUnreadBadge,
12204
12300
  writeReadCursor: () => writeReadCursor
12205
12301
  });
12206
- import { existsSync as existsSync12, mkdirSync as mkdirSync15, readFileSync as readFileSync19, writeFileSync as writeFileSync15 } from "fs";
12302
+ import { existsSync as existsSync13, mkdirSync as mkdirSync15, readFileSync as readFileSync20, writeFileSync as writeFileSync15 } from "fs";
12207
12303
  import { homedir as homedir18 } from "os";
12208
- import { join as join19 } from "path";
12304
+ import { join as join20 } from "path";
12209
12305
  async function syncUnreadBadge(deps = {}) {
12210
12306
  const readCookie = deps.readCookie ?? readWebSessionCookie;
12211
12307
  const fetchImpl = deps.fetchImpl ?? globalThis.fetch;
12212
12308
  const cacheFile = deps.cacheFile ?? INDEX_CACHE_FILE6;
12213
12309
  try {
12214
12310
  const cookie = readCookie();
12215
- if (!cookie || !existsSync12(cacheFile)) return;
12311
+ if (!cookie || !existsSync13(cacheFile)) return;
12216
12312
  const res = await fetchImpl(`${CHAT_BASE2}/api/chat/inbox`, {
12217
12313
  method: "GET",
12218
- headers: { Cookie: `${GH_SESSION_COOKIE4}=${cookie}` },
12314
+ headers: { Cookie: `${GH_SESSION_COOKIE5}=${cookie}` },
12219
12315
  signal: AbortSignal.timeout(2500)
12220
12316
  });
12221
12317
  if (!res.ok) return;
@@ -12225,7 +12321,7 @@ async function syncUnreadBadge(deps = {}) {
12225
12321
  (sum, it) => sum + (it && typeof it.unreadCount === "number" && it.unreadCount > 0 ? it.unreadCount : 0),
12226
12322
  0
12227
12323
  );
12228
- const entry = JSON.parse(readFileSync19(cacheFile, "utf8"));
12324
+ const entry = JSON.parse(readFileSync20(cacheFile, "utf8"));
12229
12325
  entry.unreadChat = { count: total };
12230
12326
  writeFileSync15(cacheFile, JSON.stringify(entry), "utf8");
12231
12327
  } catch {
@@ -12233,8 +12329,8 @@ async function syncUnreadBadge(deps = {}) {
12233
12329
  }
12234
12330
  function readReadCursors() {
12235
12331
  try {
12236
- if (!existsSync12(READS_FILE)) return {};
12237
- const parsed = JSON.parse(readFileSync19(READS_FILE, "utf8"));
12332
+ if (!existsSync13(READS_FILE)) return {};
12333
+ const parsed = JSON.parse(readFileSync20(READS_FILE, "utf8"));
12238
12334
  if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return {};
12239
12335
  const out = {};
12240
12336
  for (const [login, iso] of Object.entries(parsed)) {
@@ -12261,7 +12357,7 @@ async function postReadCursor(peerLogin, lastReadAt, deps = {}) {
12261
12357
  try {
12262
12358
  await fetch(`${CHAT_BASE2}/api/chat/read-cursor`, {
12263
12359
  method: "POST",
12264
- headers: { "Content-Type": "application/json", Cookie: `${GH_SESSION_COOKIE4}=${cookie}` },
12360
+ headers: { "Content-Type": "application/json", Cookie: `${GH_SESSION_COOKIE5}=${cookie}` },
12265
12361
  body: JSON.stringify({ peerLogin, lastReadAt }),
12266
12362
  // Best-effort cross-device sync — not latency-sensitive, so a short bound
12267
12363
  // keeps a cold/unreachable server from stalling the reader's exit.
@@ -12570,7 +12666,7 @@ async function runSend(opts = {}) {
12570
12666
  );
12571
12667
  return { ok: true };
12572
12668
  }
12573
- var CHAT_BASE2, GH_SESSION_COOKIE4, TERMINALHIRE_DIR15, READS_FILE, INDEX_CACHE_FILE6, REACHABLE_DISPLAY;
12669
+ var CHAT_BASE2, GH_SESSION_COOKIE5, TERMINALHIRE_DIR15, READS_FILE, INDEX_CACHE_FILE6, REACHABLE_DISPLAY;
12574
12670
  var init_jpi_chat_read = __esm({
12575
12671
  "bin/jpi-chat-read.js"() {
12576
12672
  "use strict";
@@ -12578,10 +12674,10 @@ var init_jpi_chat_read = __esm({
12578
12674
  init_web_session();
12579
12675
  init_jpi_chat();
12580
12676
  CHAT_BASE2 = process.env["TERMINALHIRE_API_URL"] || "https://terminalhire.com";
12581
- GH_SESSION_COOKIE4 = "__jpi_gh_session";
12582
- TERMINALHIRE_DIR15 = process.env.TERMINALHIRE_DIR || join19(homedir18(), ".terminalhire");
12583
- READS_FILE = join19(TERMINALHIRE_DIR15, "chat-reads.json");
12584
- INDEX_CACHE_FILE6 = join19(TERMINALHIRE_DIR15, "index-cache.json");
12677
+ GH_SESSION_COOKIE5 = "__jpi_gh_session";
12678
+ TERMINALHIRE_DIR15 = process.env.TERMINALHIRE_DIR || join20(homedir18(), ".terminalhire");
12679
+ READS_FILE = join20(TERMINALHIRE_DIR15, "chat-reads.json");
12680
+ INDEX_CACHE_FILE6 = join20(TERMINALHIRE_DIR15, "index-cache.json");
12585
12681
  REACHABLE_DISPLAY = { shareActivity: false, optin: false, lastSeen: null };
12586
12682
  }
12587
12683
  });
@@ -13121,16 +13217,16 @@ __export(jpi_chat_exports, {
13121
13217
  runShareActivityCommand: () => runShareActivityCommand,
13122
13218
  sanitizeLine: () => sanitizeLine
13123
13219
  });
13124
- import { createInterface as createInterface8 } from "readline";
13125
- import { existsSync as existsSync13, readFileSync as readFileSync20 } from "fs";
13220
+ import { createInterface as createInterface9 } from "readline";
13221
+ import { existsSync as existsSync14, readFileSync as readFileSync21 } from "fs";
13126
13222
  import { homedir as homedir19 } from "os";
13127
- import { join as join20 } from "path";
13223
+ import { join as join21 } from "path";
13128
13224
  function sanitizeLine(text) {
13129
13225
  return String(text).replace(ANSI_CSI, "").replace(ANSI_OSC, "").replace(ANSI_OTHER, "").replace(C0_C1_DEL, "");
13130
13226
  }
13131
13227
  function defaultPromptAck({ input = process.stdin, output = process.stdout } = {}) {
13132
13228
  if (!input || input.isTTY !== true) return Promise.resolve(false);
13133
- const rl = createInterface8({ input, output });
13229
+ const rl = createInterface9({ input, output });
13134
13230
  return new Promise((resolve2) => {
13135
13231
  rl.question(" Press Enter to acknowledge and continue (Ctrl-C to cancel): ", () => {
13136
13232
  rl.close();
@@ -13179,7 +13275,7 @@ async function fetchIntroList(deps = {}) {
13179
13275
  try {
13180
13276
  res = await fetchImpl(`${CHAT_BASE3}/api/intro/list`, {
13181
13277
  method: "GET",
13182
- headers: { Cookie: `${GH_SESSION_COOKIE5}=${cookie}` },
13278
+ headers: { Cookie: `${GH_SESSION_COOKIE6}=${cookie}` },
13183
13279
  signal: AbortSignal.timeout(1e4)
13184
13280
  });
13185
13281
  } catch (err) {
@@ -13293,9 +13389,9 @@ function mergeMessages(existing, incoming) {
13293
13389
  }
13294
13390
  function readCachedSessionStale() {
13295
13391
  try {
13296
- const p = join20(process.env.TERMINALHIRE_DIR || join20(homedir19(), ".terminalhire"), "index-cache.json");
13297
- if (!existsSync13(p)) return false;
13298
- const cache = JSON.parse(readFileSync20(p, "utf8"));
13392
+ const p = join21(process.env.TERMINALHIRE_DIR || join21(homedir19(), ".terminalhire"), "index-cache.json");
13393
+ if (!existsSync14(p)) return false;
13394
+ const cache = JSON.parse(readFileSync21(p, "utf8"));
13299
13395
  return cache?.sessionStale === true;
13300
13396
  } catch {
13301
13397
  return false;
@@ -13893,7 +13989,7 @@ async function run11() {
13893
13989
  process.exit(1);
13894
13990
  }
13895
13991
  }
13896
- var CHAT_BASE3, GH_SESSION_COOKIE5, HIDE_CURSOR2, SHOW_CURSOR2, ENTER_ALT2, EXIT_ALT2, CLEAR2, KEY_CTRL_C2, KEY_ESC2, KEY_CTRL_S, KEY_ENTER_A2, KEY_ENTER_B2, KEY_BACKSPACE_A2, KEY_BACKSPACE_B2, MAX_INPUT_LEN, ANSI_CSI, ANSI_OSC, ANSI_OTHER, C0_C1_DEL, CHAT_DISCLOSURE, CHAT_AT_REST, CHAT_CODE_OF_CONDUCT, CHAT_MIN_AGE, DEPOSIT_CTA, ACTIVE_WINDOW_MS;
13992
+ var CHAT_BASE3, GH_SESSION_COOKIE6, HIDE_CURSOR2, SHOW_CURSOR2, ENTER_ALT2, EXIT_ALT2, CLEAR2, KEY_CTRL_C2, KEY_ESC2, KEY_CTRL_S, KEY_ENTER_A2, KEY_ENTER_B2, KEY_BACKSPACE_A2, KEY_BACKSPACE_B2, MAX_INPUT_LEN, ANSI_CSI, ANSI_OSC, ANSI_OTHER, C0_C1_DEL, CHAT_DISCLOSURE, CHAT_AT_REST, CHAT_CODE_OF_CONDUCT, CHAT_MIN_AGE, DEPOSIT_CTA, ACTIVE_WINDOW_MS;
13897
13993
  var init_jpi_chat = __esm({
13898
13994
  "bin/jpi-chat.js"() {
13899
13995
  "use strict";
@@ -13901,7 +13997,7 @@ var init_jpi_chat = __esm({
13901
13997
  init_config();
13902
13998
  init_web_session();
13903
13999
  CHAT_BASE3 = process.env["TERMINALHIRE_API_URL"] || "https://terminalhire.com";
13904
- GH_SESSION_COOKIE5 = "__jpi_gh_session";
14000
+ GH_SESSION_COOKIE6 = "__jpi_gh_session";
13905
14001
  HIDE_CURSOR2 = "\x1B[?25l";
13906
14002
  SHOW_CURSOR2 = "\x1B[?25h";
13907
14003
  ENTER_ALT2 = "\x1B[?1049h";
@@ -13946,15 +14042,15 @@ __export(mcp_config_exports, {
13946
14042
  writeServerToFile: () => writeServerToFile
13947
14043
  });
13948
14044
  import { homedir as homedir20 } from "os";
13949
- import { join as join21 } from "path";
13950
- import { existsSync as existsSync14, readFileSync as readFileSync21, copyFileSync as copyFileSync2, writeFileSync as writeFileSync16, mkdirSync as mkdirSync16 } from "fs";
14045
+ import { join as join22 } from "path";
14046
+ import { existsSync as existsSync15, readFileSync as readFileSync22, copyFileSync as copyFileSync2, writeFileSync as writeFileSync16, mkdirSync as mkdirSync16 } from "fs";
13951
14047
  import { dirname as dirname2 } from "path";
13952
14048
  function serverEntry() {
13953
14049
  return { command: SERVER_COMMAND, args: [...SERVER_ARGS] };
13954
14050
  }
13955
14051
  function hostConfigPath(host, home = homedir20()) {
13956
14052
  if (!host || !Array.isArray(host.relPath)) return null;
13957
- return join21(home, ...host.relPath);
14053
+ return join22(home, ...host.relPath);
13958
14054
  }
13959
14055
  function jsonSnippet(host) {
13960
14056
  const entry = serverEntry();
@@ -14038,8 +14134,8 @@ function mergeServerIntoJson(existingText, serversKey, entry = serverEntry()) {
14038
14134
  `, added: !already };
14039
14135
  }
14040
14136
  function writeServerToFile(configPath, serversKey, entry = serverEntry()) {
14041
- const fileExists = existsSync14(configPath);
14042
- const existingText = fileExists ? readFileSync21(configPath, "utf8") : "";
14137
+ const fileExists = existsSync15(configPath);
14138
+ const existingText = fileExists ? readFileSync22(configPath, "utf8") : "";
14043
14139
  const merged = mergeServerIntoJson(existingText, serversKey, entry);
14044
14140
  if (!merged.ok) {
14045
14141
  return { status: "skipped", reason: merged.reason };
@@ -14081,7 +14177,7 @@ async function initMcpStep({
14081
14177
  return;
14082
14178
  }
14083
14179
  const writableHosts = HOSTS.filter((h) => h.writable);
14084
- const detected = writableHosts.filter((h) => existsSync14(hostConfigPath(h, home)));
14180
+ const detected = writableHosts.filter((h) => existsSync15(hostConfigPath(h, home)));
14085
14181
  if (detected.length === 0) {
14086
14182
  out("");
14087
14183
  out(" No editor/CLI config detected (looked for ~/.cursor/mcp.json, ~/.gemini/settings.json).");
@@ -36323,13 +36419,13 @@ async function run12() {
36323
36419
  const { ListToolsRequestSchema: ListToolsRequestSchema2, CallToolRequestSchema: CallToolRequestSchema2 } = await Promise.resolve().then(() => (init_types3(), types_exports));
36324
36420
  let version2 = "0.0.0";
36325
36421
  try {
36326
- const { readFileSync: readFileSync30, existsSync: existsSync22 } = await import("fs");
36327
- const { join: join33 } = await import("path");
36328
- const { fileURLToPath: fileURLToPath9 } = await import("url");
36329
- const here = fileURLToPath9(new URL(".", import.meta.url));
36330
- for (const p of [join33(here, "..", "..", "package.json"), join33(here, "..", "package.json")]) {
36331
- if (existsSync22(p)) {
36332
- const pkg = JSON.parse(readFileSync30(p, "utf8"));
36422
+ const { readFileSync: readFileSync31, existsSync: existsSync23 } = await import("fs");
36423
+ const { join: join34 } = await import("path");
36424
+ const { fileURLToPath: fileURLToPath10 } = await import("url");
36425
+ const here = fileURLToPath10(new URL(".", import.meta.url));
36426
+ for (const p of [join34(here, "..", "..", "package.json"), join34(here, "..", "package.json")]) {
36427
+ if (existsSync23(p)) {
36428
+ const pkg = JSON.parse(readFileSync31(p, "utf8"));
36333
36429
  if (pkg.version) {
36334
36430
  version2 = pkg.version;
36335
36431
  break;
@@ -36609,7 +36705,7 @@ async function runLinkLogout(overrides) {
36609
36705
  try {
36610
36706
  const res = await deps.fetchImpl(`${LINK_BASE3}/api/auth/session`, {
36611
36707
  method: "DELETE",
36612
- headers: { Cookie: `${GH_SESSION_COOKIE6}=${token}` },
36708
+ headers: { Cookie: `${GH_SESSION_COOKIE7}=${token}` },
36613
36709
  signal: AbortSignal.timeout(1e4)
36614
36710
  });
36615
36711
  revoked = res.ok;
@@ -36624,14 +36720,14 @@ async function runLinkLogout(overrides) {
36624
36720
  }
36625
36721
  deps.exit(0);
36626
36722
  }
36627
- var LINK_BASE3, GH_SESSION_COOKIE6, LINK_TIMEOUT_MS, LINKED_HTML, FAILED_HTML;
36723
+ var LINK_BASE3, GH_SESSION_COOKIE7, LINK_TIMEOUT_MS, LINKED_HTML, FAILED_HTML;
36628
36724
  var init_link = __esm({
36629
36725
  "src/link.ts"() {
36630
36726
  "use strict";
36631
36727
  init_web_session();
36632
36728
  init_config();
36633
36729
  LINK_BASE3 = "https://terminalhire.com";
36634
- GH_SESSION_COOKIE6 = "__jpi_gh_session";
36730
+ GH_SESSION_COOKIE7 = "__jpi_gh_session";
36635
36731
  LINK_TIMEOUT_MS = 12e4;
36636
36732
  LINKED_HTML = `<!doctype html><html><head><meta charset="utf-8"><title>terminalhire</title></head>
36637
36733
  <body style="font-family:system-ui;padding:2rem;background:#0b0d10;color:#e6e6e6">
@@ -36681,9 +36777,9 @@ var jpi_profile_exports = {};
36681
36777
  __export(jpi_profile_exports, {
36682
36778
  run: () => run15
36683
36779
  });
36684
- import { createInterface as createInterface9 } from "readline";
36780
+ import { createInterface as createInterface10 } from "readline";
36685
36781
  function prompt4(question) {
36686
- const rl = createInterface9({ input: process.stdin, output: process.stdout });
36782
+ const rl = createInterface10({ input: process.stdin, output: process.stdout });
36687
36783
  return new Promise((resolve2) => {
36688
36784
  rl.question(question, (answer) => {
36689
36785
  rl.close();
@@ -36764,9 +36860,9 @@ var signal_exports = {};
36764
36860
  __export(signal_exports, {
36765
36861
  extractFingerprint: () => extractFingerprint
36766
36862
  });
36767
- import { readFileSync as readFileSync22, readdirSync as readdirSync2 } from "fs";
36863
+ import { readFileSync as readFileSync23, readdirSync as readdirSync2 } from "fs";
36768
36864
  import { execFileSync } from "child_process";
36769
- import { join as join22 } from "path";
36865
+ import { join as join23 } from "path";
36770
36866
  function safeGit(args5, cwd) {
36771
36867
  try {
36772
36868
  return execFileSync("git", ["-C", cwd, ...args5], {
@@ -36794,20 +36890,20 @@ function isEmployerContext(cwd) {
36794
36890
  }
36795
36891
  function readJsonSafe(path) {
36796
36892
  try {
36797
- return JSON.parse(readFileSync22(path, "utf8"));
36893
+ return JSON.parse(readFileSync23(path, "utf8"));
36798
36894
  } catch {
36799
36895
  return null;
36800
36896
  }
36801
36897
  }
36802
36898
  function readFileSafe(path) {
36803
36899
  try {
36804
- return readFileSync22(path, "utf8");
36900
+ return readFileSync23(path, "utf8");
36805
36901
  } catch {
36806
36902
  return "";
36807
36903
  }
36808
36904
  }
36809
36905
  function tokensFromPackageJson(cwd) {
36810
- const pkg = readJsonSafe(join22(cwd, "package.json"));
36906
+ const pkg = readJsonSafe(join23(cwd, "package.json"));
36811
36907
  if (!pkg || typeof pkg !== "object") return [];
36812
36908
  const p = pkg;
36813
36909
  const deps = {
@@ -36821,9 +36917,9 @@ function workspaceMemberDirs(cwd) {
36821
36917
  const dirs = [cwd];
36822
36918
  for (const group of ["apps", "packages"]) {
36823
36919
  try {
36824
- const groupDir = join22(cwd, group);
36920
+ const groupDir = join23(cwd, group);
36825
36921
  for (const e of readdirSync2(groupDir, { withFileTypes: true })) {
36826
- if (e.isDirectory() && !e.isSymbolicLink()) dirs.push(join22(groupDir, e.name));
36922
+ if (e.isDirectory() && !e.isSymbolicLink()) dirs.push(join23(groupDir, e.name));
36827
36923
  }
36828
36924
  } catch {
36829
36925
  }
@@ -36831,18 +36927,18 @@ function workspaceMemberDirs(cwd) {
36831
36927
  return dirs;
36832
36928
  }
36833
36929
  function tokensFromRequirementsTxt(cwd) {
36834
- const content = readFileSafe(join22(cwd, "requirements.txt"));
36930
+ const content = readFileSafe(join23(cwd, "requirements.txt"));
36835
36931
  if (!content) return [];
36836
36932
  return content.split("\n").map((l) => l.trim().split(/[>=<!\[;]/)[0].trim().toLowerCase()).filter(Boolean);
36837
36933
  }
36838
36934
  function tokensFromGoMod(cwd) {
36839
- const content = readFileSafe(join22(cwd, "go.mod"));
36935
+ const content = readFileSafe(join23(cwd, "go.mod"));
36840
36936
  if (!content) return [];
36841
36937
  const requires = Array.from(content.matchAll(/^\s+([^\s]+)\s+v/gm)).map((m) => m[1].split("/").pop() ?? "").filter(Boolean);
36842
36938
  return ["go", ...requires];
36843
36939
  }
36844
36940
  function tokensFromCargoToml(cwd) {
36845
- const content = readFileSafe(join22(cwd, "Cargo.toml"));
36941
+ const content = readFileSafe(join23(cwd, "Cargo.toml"));
36846
36942
  if (!content) return [];
36847
36943
  const deps = [];
36848
36944
  let inDeps = false;
@@ -36863,7 +36959,7 @@ function tokensFromFileExtensions(cwd) {
36863
36959
  const tokens = [];
36864
36960
  const scanDirs = [cwd];
36865
36961
  try {
36866
- const srcDir = join22(cwd, "src");
36962
+ const srcDir = join23(cwd, "src");
36867
36963
  readdirSync2(srcDir);
36868
36964
  scanDirs.push(srcDir);
36869
36965
  } catch {
@@ -37063,7 +37159,7 @@ var jpi_config_exports = {};
37063
37159
  __export(jpi_config_exports, {
37064
37160
  run: () => run17
37065
37161
  });
37066
- import { join as join23 } from "path";
37162
+ import { join as join24 } from "path";
37067
37163
  import { homedir as homedir21 } from "os";
37068
37164
  function parseNudgeMode2(raw) {
37069
37165
  if (raw === "session" || raw === "always") return raw;
@@ -37137,33 +37233,33 @@ var init_jpi_config = __esm({
37137
37233
  "bin/jpi-config.js"() {
37138
37234
  "use strict";
37139
37235
  init_config();
37140
- TERMINALHIRE_DIR16 = process.env.TERMINALHIRE_DIR || join23(homedir21(), ".terminalhire");
37141
- CONFIG_FILE2 = join23(TERMINALHIRE_DIR16, "config.json");
37236
+ TERMINALHIRE_DIR16 = process.env.TERMINALHIRE_DIR || join24(homedir21(), ".terminalhire");
37237
+ CONFIG_FILE2 = join24(TERMINALHIRE_DIR16, "config.json");
37142
37238
  }
37143
37239
  });
37144
37240
 
37145
37241
  // bin/spinner-io.js
37146
37242
  import {
37147
- readFileSync as readFileSync23,
37243
+ readFileSync as readFileSync24,
37148
37244
  writeFileSync as writeFileSync17,
37149
- existsSync as existsSync15,
37245
+ existsSync as existsSync16,
37150
37246
  mkdirSync as mkdirSync17,
37151
37247
  renameSync as renameSync4
37152
37248
  } from "fs";
37153
- import { join as join24, dirname as dirname3 } from "path";
37249
+ import { join as join25, dirname as dirname3 } from "path";
37154
37250
  import { homedir as homedir22 } from "os";
37155
37251
  function thDir() {
37156
- return process.env["TERMINALHIRE_DIR"] || join24(homedir22(), ".terminalhire");
37252
+ return process.env["TERMINALHIRE_DIR"] || join25(homedir22(), ".terminalhire");
37157
37253
  }
37158
37254
  function claudeSettingsPath() {
37159
- return process.env["TERMINALHIRE_CLAUDE_SETTINGS"] || join24(homedir22(), ".claude", "settings.json");
37255
+ return process.env["TERMINALHIRE_CLAUDE_SETTINGS"] || join25(homedir22(), ".claude", "settings.json");
37160
37256
  }
37161
37257
  function spinnerStateFilePath() {
37162
- return join24(thDir(), "spinner-state.json");
37258
+ return join25(thDir(), "spinner-state.json");
37163
37259
  }
37164
37260
  function readJson(path, fallback) {
37165
37261
  try {
37166
- return existsSync15(path) ? JSON.parse(readFileSync23(path, "utf8")) : fallback;
37262
+ return existsSync16(path) ? JSON.parse(readFileSync24(path, "utf8")) : fallback;
37167
37263
  } catch {
37168
37264
  return fallback;
37169
37265
  }
@@ -37268,9 +37364,9 @@ var init_spinner_io = __esm({
37268
37364
  });
37269
37365
 
37270
37366
  // bin/spinner-config.js
37271
- import { join as join25 } from "path";
37367
+ import { join as join26 } from "path";
37272
37368
  function configFilePath() {
37273
- return join25(thDir(), "config.json");
37369
+ return join26(thDir(), "config.json");
37274
37370
  }
37275
37371
  function readSpinnerConfig() {
37276
37372
  const CONFIG_FILE4 = configFilePath();
@@ -37306,16 +37402,16 @@ __export(spinner_seen_exports, {
37306
37402
  seenFilePath: () => seenFilePath
37307
37403
  });
37308
37404
  import {
37309
- readFileSync as readFileSync24,
37405
+ readFileSync as readFileSync25,
37310
37406
  writeFileSync as writeFileSync18,
37311
37407
  renameSync as renameSync5,
37312
37408
  mkdirSync as mkdirSync18
37313
37409
  } from "fs";
37314
- import { join as join26, dirname as dirname4 } from "path";
37410
+ import { join as join27, dirname as dirname4 } from "path";
37315
37411
  import { homedir as homedir23 } from "os";
37316
37412
  function seenFilePath() {
37317
- const dir = process.env["TERMINALHIRE_DIR"] || join26(homedir23(), ".terminalhire");
37318
- return join26(dir, "seen-history.json");
37413
+ const dir = process.env["TERMINALHIRE_DIR"] || join27(homedir23(), ".terminalhire");
37414
+ return join27(dir, "seen-history.json");
37319
37415
  }
37320
37416
  function atomicWriteJson3(path, obj) {
37321
37417
  mkdirSync18(dirname4(path), { recursive: true });
@@ -37349,7 +37445,7 @@ function capEntries(entries) {
37349
37445
  function loadSeenHistory(now = Date.now()) {
37350
37446
  let raw;
37351
37447
  try {
37352
- raw = JSON.parse(readFileSync24(seenFilePath(), "utf8"));
37448
+ raw = JSON.parse(readFileSync25(seenFilePath(), "utf8"));
37353
37449
  } catch {
37354
37450
  return emptyHistory();
37355
37451
  }
@@ -37792,18 +37888,18 @@ __export(jpi_spinner_exports, {
37792
37888
  run: () => run18
37793
37889
  });
37794
37890
  import {
37795
- readFileSync as readFileSync25,
37891
+ readFileSync as readFileSync26,
37796
37892
  writeFileSync as writeFileSync19,
37797
37893
  copyFileSync as copyFileSync3,
37798
- existsSync as existsSync16,
37894
+ existsSync as existsSync17,
37799
37895
  mkdirSync as mkdirSync19
37800
37896
  } from "fs";
37801
- import { join as join27 } from "path";
37897
+ import { join as join28 } from "path";
37802
37898
  import { homedir as homedir24 } from "os";
37803
- import { createInterface as createInterface10 } from "readline";
37899
+ import { createInterface as createInterface11 } from "readline";
37804
37900
  function readConfig2() {
37805
37901
  try {
37806
- return existsSync16(CONFIG_FILE3) ? JSON.parse(readFileSync25(CONFIG_FILE3, "utf8")) : {};
37902
+ return existsSync17(CONFIG_FILE3) ? JSON.parse(readFileSync26(CONFIG_FILE3, "utf8")) : {};
37807
37903
  } catch {
37808
37904
  return {};
37809
37905
  }
@@ -37814,14 +37910,14 @@ function writeConfig2(patch) {
37814
37910
  writeFileSync19(CONFIG_FILE3, JSON.stringify(merged, null, 2) + "\n", "utf8");
37815
37911
  }
37816
37912
  function backupSettings() {
37817
- if (!existsSync16(SETTINGS_PATH)) return null;
37913
+ if (!existsSync17(SETTINGS_PATH)) return null;
37818
37914
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
37819
37915
  const backupPath = `${SETTINGS_PATH}.terminalhire-backup-${ts}`;
37820
37916
  copyFileSync3(SETTINGS_PATH, backupPath);
37821
37917
  return backupPath;
37822
37918
  }
37823
37919
  function ask(question) {
37824
- const rl = createInterface10({ input: process.stdin, output: process.stdout });
37920
+ const rl = createInterface11({ input: process.stdin, output: process.stdout });
37825
37921
  return new Promise((res) => {
37826
37922
  rl.question(question, (answer) => {
37827
37923
  rl.close();
@@ -37831,7 +37927,7 @@ function ask(question) {
37831
37927
  }
37832
37928
  function readTopMatches() {
37833
37929
  try {
37834
- const c = JSON.parse(readFileSync25(CACHE_FILE, "utf8"));
37930
+ const c = JSON.parse(readFileSync26(CACHE_FILE, "utf8"));
37835
37931
  return Array.isArray(c.topMatches) ? c.topMatches : [];
37836
37932
  } catch {
37837
37933
  return [];
@@ -37974,10 +38070,10 @@ var init_jpi_spinner = __esm({
37974
38070
  "bin/jpi-spinner.js"() {
37975
38071
  "use strict";
37976
38072
  init_spinner();
37977
- TH_DIR = process.env["TERMINALHIRE_DIR"] || join27(homedir24(), ".terminalhire");
37978
- CONFIG_FILE3 = join27(TH_DIR, "config.json");
37979
- SETTINGS_PATH = process.env["TERMINALHIRE_CLAUDE_SETTINGS"] || join27(homedir24(), ".claude", "settings.json");
37980
- CACHE_FILE = join27(TH_DIR, "index-cache.json");
38073
+ TH_DIR = process.env["TERMINALHIRE_DIR"] || join28(homedir24(), ".terminalhire");
38074
+ CONFIG_FILE3 = join28(TH_DIR, "config.json");
38075
+ SETTINGS_PATH = process.env["TERMINALHIRE_CLAUDE_SETTINGS"] || join28(homedir24(), ".claude", "settings.json");
38076
+ CACHE_FILE = join28(TH_DIR, "index-cache.json");
37981
38077
  }
37982
38078
  });
37983
38079
 
@@ -37986,12 +38082,12 @@ var jpi_sync_exports = {};
37986
38082
  __export(jpi_sync_exports, {
37987
38083
  run: () => run19
37988
38084
  });
37989
- import { readFileSync as readFileSync26, writeFileSync as writeFileSync20, mkdirSync as mkdirSync20, existsSync as existsSync17, rmSync as rmSync5 } from "fs";
37990
- import { join as join28 } from "path";
38085
+ import { readFileSync as readFileSync27, writeFileSync as writeFileSync20, mkdirSync as mkdirSync20, existsSync as existsSync18, rmSync as rmSync5 } from "fs";
38086
+ import { join as join29 } from "path";
37991
38087
  import { homedir as homedir25, hostname as osHostname2 } from "os";
37992
- import { createInterface as createInterface11 } from "readline";
38088
+ import { createInterface as createInterface12 } from "readline";
37993
38089
  function ask2(question) {
37994
- const rl = createInterface11({ input: process.stdin, output: process.stdout });
38090
+ const rl = createInterface12({ input: process.stdin, output: process.stdout });
37995
38091
  return new Promise((res) => {
37996
38092
  rl.question(question, (answer) => {
37997
38093
  rl.close();
@@ -38001,7 +38097,7 @@ function ask2(question) {
38001
38097
  }
38002
38098
  function readMarker() {
38003
38099
  try {
38004
- return existsSync17(TIER1_MARKER) ? JSON.parse(readFileSync26(TIER1_MARKER, "utf8")) : null;
38100
+ return existsSync18(TIER1_MARKER) ? JSON.parse(readFileSync27(TIER1_MARKER, "utf8")) : null;
38005
38101
  } catch {
38006
38102
  return null;
38007
38103
  }
@@ -38074,7 +38170,7 @@ async function runPush() {
38074
38170
  const fields = buildConsentFields(profile);
38075
38171
  renderPreview(fields);
38076
38172
  await new Promise((resolve2) => {
38077
- const rl = createInterface11({ input: process.stdin, output: process.stdout });
38173
+ const rl = createInterface12({ input: process.stdin, output: process.stdout });
38078
38174
  rl.question(
38079
38175
  " Press Enter to open your browser to authorize + consent (or Ctrl-C to cancel)... ",
38080
38176
  () => {
@@ -38327,8 +38423,8 @@ var init_jpi_sync = __esm({
38327
38423
  "bin/jpi-sync.js"() {
38328
38424
  "use strict";
38329
38425
  init_open_url();
38330
- TH_DIR2 = process.env["TERMINALHIRE_DIR"] || join28(homedir25(), ".terminalhire");
38331
- TIER1_MARKER = join28(TH_DIR2, "tier1.json");
38426
+ TH_DIR2 = process.env["TERMINALHIRE_DIR"] || join29(homedir25(), ".terminalhire");
38427
+ TIER1_MARKER = join29(TH_DIR2, "tier1.json");
38332
38428
  API_URL7 = process.env["TERMINALHIRE_API_URL"] || process.env["JPI_API_URL"] || "https://terminalhire.com";
38333
38429
  SYNC_BASE = "https://terminalhire.com";
38334
38430
  POLL_INTERVAL_MS = 2e3;
@@ -38342,37 +38438,37 @@ var jpi_init_exports = {};
38342
38438
  __export(jpi_init_exports, {
38343
38439
  run: () => run20
38344
38440
  });
38345
- import { existsSync as existsSync18 } from "fs";
38346
- import { join as join29, resolve } from "path";
38347
- import { fileURLToPath as fileURLToPath4, pathToFileURL } from "url";
38348
- import { createInterface as createInterface12 } from "readline";
38441
+ import { existsSync as existsSync19 } from "fs";
38442
+ import { join as join30, resolve } from "path";
38443
+ import { fileURLToPath as fileURLToPath5, pathToFileURL } from "url";
38444
+ import { createInterface as createInterface13 } from "readline";
38349
38445
  import { spawnSync } from "child_process";
38350
38446
  function resolveScript(name) {
38351
- const distPath = resolve(join29(__dirname3, "..", "..", "dist", "bin", `${name}.js`));
38352
- const legacyPath = resolve(join29(__dirname3, `${name}.js`));
38353
- return existsSync18(distPath) ? distPath : legacyPath;
38447
+ const distPath = resolve(join30(__dirname4, "..", "..", "dist", "bin", `${name}.js`));
38448
+ const legacyPath = resolve(join30(__dirname4, `${name}.js`));
38449
+ return existsSync19(distPath) ? distPath : legacyPath;
38354
38450
  }
38355
38451
  function resolveSrc(name) {
38356
- const distPath = resolve(join29(__dirname3, "..", "..", "dist", "src", `${name}.js`));
38357
- const legacyPath = resolve(join29(__dirname3, "..", "src", `${name}.js`));
38358
- return existsSync18(distPath) ? distPath : legacyPath;
38452
+ const distPath = resolve(join30(__dirname4, "..", "..", "dist", "src", `${name}.js`));
38453
+ const legacyPath = resolve(join30(__dirname4, "..", "src", `${name}.js`));
38454
+ return existsSync19(distPath) ? distPath : legacyPath;
38359
38455
  }
38360
38456
  function resolveInstallJs() {
38361
- const fromDist = resolve(join29(__dirname3, "..", "..", "install.js"));
38362
- const fromBin = resolve(join29(__dirname3, "..", "install.js"));
38363
- if (existsSync18(fromDist)) return fromDist;
38364
- if (existsSync18(fromBin)) return fromBin;
38457
+ const fromDist = resolve(join30(__dirname4, "..", "..", "install.js"));
38458
+ const fromBin = resolve(join30(__dirname4, "..", "install.js"));
38459
+ if (existsSync19(fromDist)) return fromDist;
38460
+ if (existsSync19(fromBin)) return fromBin;
38365
38461
  return fromBin;
38366
38462
  }
38367
38463
  function resolveStatuslineInstallJs() {
38368
- const fromDist = resolve(join29(__dirname3, "..", "..", "statusline-install.js"));
38369
- const fromBin = resolve(join29(__dirname3, "..", "statusline-install.js"));
38370
- if (existsSync18(fromDist)) return fromDist;
38371
- if (existsSync18(fromBin)) return fromBin;
38464
+ const fromDist = resolve(join30(__dirname4, "..", "..", "statusline-install.js"));
38465
+ const fromBin = resolve(join30(__dirname4, "..", "statusline-install.js"));
38466
+ if (existsSync19(fromDist)) return fromDist;
38467
+ if (existsSync19(fromBin)) return fromBin;
38372
38468
  return fromBin;
38373
38469
  }
38374
38470
  async function run20() {
38375
- const rl = createInterface12({ input: process.stdin, output: process.stdout });
38471
+ const rl = createInterface13({ input: process.stdin, output: process.stdout });
38376
38472
  const ask3 = (question) => new Promise((resolve2) => {
38377
38473
  let answered = false;
38378
38474
  rl.question(question, (answer) => {
@@ -38539,11 +38635,11 @@ async function run20() {
38539
38635
  console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518");
38540
38636
  console.log("");
38541
38637
  }
38542
- var __dirname3;
38638
+ var __dirname4;
38543
38639
  var init_jpi_init = __esm({
38544
38640
  "bin/jpi-init.js"() {
38545
38641
  "use strict";
38546
- __dirname3 = fileURLToPath4(new URL(".", import.meta.url));
38642
+ __dirname4 = fileURLToPath5(new URL(".", import.meta.url));
38547
38643
  }
38548
38644
  });
38549
38645
 
@@ -38593,7 +38689,7 @@ var init_match_slots = __esm({
38593
38689
  BOUNTY_SLOTS = 3;
38594
38690
  BOUNTY_MIN_MATCH = 0.5;
38595
38691
  INTEREST_CONTRIBUTE_SLOTS = 1;
38596
- INTEREST_SLOT_LABEL = "Exploring";
38692
+ INTEREST_SLOT_LABEL = "Stretch";
38597
38693
  CONTRIBUTE_SLOTS = 5;
38598
38694
  CONTRIBUTE_SLOTS_THIN = 8;
38599
38695
  ROLE_STABLE_MAX = 8;
@@ -38664,7 +38760,7 @@ var jpi_refresh_exports = {};
38664
38760
  __export(jpi_refresh_exports, {
38665
38761
  run: () => run21
38666
38762
  });
38667
- import { fileURLToPath as fileURLToPath5 } from "url";
38763
+ import { fileURLToPath as fileURLToPath6 } from "url";
38668
38764
  async function run21() {
38669
38765
  try {
38670
38766
  let index;
@@ -38830,7 +38926,7 @@ async function run21() {
38830
38926
  if (sessionCookie && !isInboundNudgeMuted()) try {
38831
38927
  const res = await fetch(`${API_URL8}/api/intro/list`, {
38832
38928
  method: "GET",
38833
- headers: { Cookie: `${GH_SESSION_COOKIE7}=${sessionCookie}` },
38929
+ headers: { Cookie: `${GH_SESSION_COOKIE8}=${sessionCookie}` },
38834
38930
  signal: AbortSignal.timeout(1e4)
38835
38931
  });
38836
38932
  if (res.ok) {
@@ -38847,7 +38943,7 @@ async function run21() {
38847
38943
  if (sessionCookie && !isInboundNudgeMuted()) try {
38848
38944
  const res = await fetch(`${API_URL8}/api/chat/inbox`, {
38849
38945
  method: "GET",
38850
- headers: { Cookie: `${GH_SESSION_COOKIE7}=${sessionCookie}` },
38946
+ headers: { Cookie: `${GH_SESSION_COOKIE8}=${sessionCookie}` },
38851
38947
  signal: AbortSignal.timeout(1e4)
38852
38948
  });
38853
38949
  if (res.ok) {
@@ -38924,8 +39020,8 @@ async function run21() {
38924
39020
  } catch {
38925
39021
  }
38926
39022
  try {
38927
- const { readLocalVersion: readLocalVersion3, buildStaleNudge: buildStaleNudge2 } = await Promise.resolve().then(() => (init_version_nudge(), version_nudge_exports));
38928
- const nudge = buildStaleNudge2(readLocalVersion3(), index?.cliVersion);
39023
+ const { readLocalVersion: readLocalVersion4, buildStaleNudge: buildStaleNudge2 } = await Promise.resolve().then(() => (init_version_nudge(), version_nudge_exports));
39024
+ const nudge = buildStaleNudge2(readLocalVersion4(), index?.cliVersion);
38929
39025
  if (nudge) process.stderr.write(`${nudge}
38930
39026
  `);
38931
39027
  } catch {
@@ -38946,7 +39042,7 @@ async function run21() {
38946
39042
  process.exit(1);
38947
39043
  }
38948
39044
  }
38949
- var GH_SESSION_COOKIE7, __dirname4, API_URL8, CWD_SOFTTAGS_ENABLED, CWD_SOFTTAG_WEIGHT, PREFS_RANKING_ENABLED, DECLARED_SOFTTAG_WEIGHT, MMR_RERANK_ENABLED, MMR_LAMBDA, MMR_K;
39045
+ var GH_SESSION_COOKIE8, __dirname5, API_URL8, CWD_SOFTTAGS_ENABLED, CWD_SOFTTAG_WEIGHT, PREFS_RANKING_ENABLED, DECLARED_SOFTTAG_WEIGHT, MMR_RERANK_ENABLED, MMR_LAMBDA, MMR_K;
38950
39046
  var init_jpi_refresh = __esm({
38951
39047
  "bin/jpi-refresh.js"() {
38952
39048
  "use strict";
@@ -38957,8 +39053,8 @@ var init_jpi_refresh = __esm({
38957
39053
  init_job_status_suppress();
38958
39054
  init_config();
38959
39055
  init_web_session();
38960
- GH_SESSION_COOKIE7 = "__jpi_gh_session";
38961
- __dirname4 = fileURLToPath5(new URL(".", import.meta.url));
39056
+ GH_SESSION_COOKIE8 = "__jpi_gh_session";
39057
+ __dirname5 = fileURLToPath6(new URL(".", import.meta.url));
38962
39058
  API_URL8 = process.env["TERMINALHIRE_API_URL"] ?? process.env["JPI_API_URL"] ?? "https://terminalhire.com";
38963
39059
  CWD_SOFTTAGS_ENABLED = process.env["TH_CWD_SOFTTAGS"] !== "0";
38964
39060
  CWD_SOFTTAG_WEIGHT = 0.4;
@@ -38975,14 +39071,14 @@ var jpi_save_exports = {};
38975
39071
  __export(jpi_save_exports, {
38976
39072
  run: () => run22
38977
39073
  });
38978
- import { readFileSync as readFileSync27, existsSync as existsSync19 } from "fs";
38979
- import { join as join30 } from "path";
39074
+ import { readFileSync as readFileSync28, existsSync as existsSync20 } from "fs";
39075
+ import { join as join31 } from "path";
38980
39076
  import { homedir as homedir26 } from "os";
38981
- import { fileURLToPath as fileURLToPath6 } from "url";
39077
+ import { fileURLToPath as fileURLToPath7 } from "url";
38982
39078
  function findJobInCache(jobId) {
38983
39079
  try {
38984
- if (!existsSync19(INDEX_CACHE_FILE7)) return null;
38985
- const raw = readFileSync27(INDEX_CACHE_FILE7, "utf8");
39080
+ if (!existsSync20(INDEX_CACHE_FILE7)) return null;
39081
+ const raw = readFileSync28(INDEX_CACHE_FILE7, "utf8");
38986
39082
  const entry = JSON.parse(raw);
38987
39083
  const jobs = entry?.index?.jobs ?? [];
38988
39084
  return jobs.find((j) => j.id === jobId) ?? null;
@@ -39070,13 +39166,13 @@ async function run22() {
39070
39166
  process.exit(1);
39071
39167
  }
39072
39168
  }
39073
- var __dirname5, TERMINALHIRE_DIR17, INDEX_CACHE_FILE7;
39169
+ var __dirname6, TERMINALHIRE_DIR17, INDEX_CACHE_FILE7;
39074
39170
  var init_jpi_save = __esm({
39075
39171
  "bin/jpi-save.js"() {
39076
39172
  "use strict";
39077
- __dirname5 = fileURLToPath6(new URL(".", import.meta.url));
39078
- TERMINALHIRE_DIR17 = process.env.TERMINALHIRE_DIR || join30(homedir26(), ".terminalhire");
39079
- INDEX_CACHE_FILE7 = join30(TERMINALHIRE_DIR17, "index-cache.json");
39173
+ __dirname6 = fileURLToPath7(new URL(".", import.meta.url));
39174
+ TERMINALHIRE_DIR17 = process.env.TERMINALHIRE_DIR || join31(homedir26(), ".terminalhire");
39175
+ INDEX_CACHE_FILE7 = join31(TERMINALHIRE_DIR17, "index-cache.json");
39080
39176
  }
39081
39177
  });
39082
39178
 
@@ -39085,53 +39181,57 @@ var jpi_beta_exports = {};
39085
39181
  __export(jpi_beta_exports, {
39086
39182
  run: () => run23
39087
39183
  });
39088
- import { createInterface as createInterface13 } from "readline";
39184
+ import { createInterface as createInterface14 } from "readline";
39089
39185
  async function run23() {
39090
- const rl = createInterface13({ input: process.stdin, output: process.stdout });
39186
+ const rl = createInterface14({ input: process.stdin, output: process.stdout });
39091
39187
  const ask3 = (question) => new Promise((resolve2) => {
39092
- let answered = false;
39188
+ const onClose = () => resolve2(null);
39189
+ rl.once("close", onClose);
39093
39190
  rl.question(question, (answer) => {
39094
- answered = true;
39191
+ rl.removeListener("close", onClose);
39095
39192
  resolve2((answer || "").trim());
39096
39193
  });
39097
- rl.once("close", () => {
39098
- if (!answered) resolve2(null);
39099
- });
39100
39194
  });
39101
- console.log("");
39102
- console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510");
39103
- console.log("\u2502 Welcome to the Terminalhire Beta \u2014 Founding Contributor \u2502");
39104
- console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518");
39105
- console.log("");
39106
- console.log(` In a world where everyone's suddenly an "AI engineer," Terminalhire is`);
39107
- console.log(" third-party-verified, hard-to-game proof you're real \u2014 not a r\xE9sum\xE9, a");
39108
- console.log(" record of contributions accepted by people who don't know you.");
39109
- console.log("");
39110
- console.log(" You've been invited to help shape it while the core is still baking.");
39111
- console.log("");
39112
- console.log("The deal \u2014 two small asks, four real rewards.");
39113
- console.log("");
39114
- console.log(" Two asks:");
39115
- console.log(" 1. Use it on real work and keep it installed \u2014 the honest test of");
39116
- console.log(" whether it earns its place in your terminal.");
39117
- console.log(" 2. When something breaks or annoys you, tell us: `terminalhire feedback`");
39118
- console.log(" (2 minutes, goes straight to the founder).");
39119
- console.log("");
39120
- console.log(" Four rewards:");
39121
- console.log(" \u2022 A Founding-Contributor mark on your credential.");
39122
- console.log(" \u2022 A direct line to the founder \u2014 the person who ships the fix.");
39123
- console.log(" \u2022 Bounties on the issues your feedback surfaces \u2014 get paid for the");
39124
- console.log(" rough edges you find.");
39125
- console.log(" \u2022 A spot on the founding-contributors wall.");
39126
- console.log("");
39127
- const join33 = await ask3(' Type "yes" to join the beta as a Founding Contributor (anything else cancels): ');
39128
- if ((join33 || "").toLowerCase() !== "yes") {
39129
- console.log("\n No problem \u2014 nothing was sent. Run `terminalhire beta` any time.\n");
39130
- rl.close();
39131
- return;
39195
+ const alreadyActed = readConfig().betaOptIn === true;
39196
+ let listPublicly = false;
39197
+ if (!alreadyActed) {
39198
+ console.log("");
39199
+ console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510");
39200
+ console.log("\u2502 Welcome to the Terminalhire Beta \u2014 Founding Contributor \u2502");
39201
+ console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518");
39202
+ console.log("");
39203
+ console.log(` In a world where everyone's suddenly an "AI engineer," Terminalhire is`);
39204
+ console.log(" third-party-verified, hard-to-game proof you're real \u2014 not a r\xE9sum\xE9, a");
39205
+ console.log(" record of contributions accepted by people who don't know you.");
39206
+ console.log("");
39207
+ console.log(" You've been invited to help shape it while the core is still baking.");
39208
+ console.log("");
39209
+ console.log("The deal \u2014 two small asks, four real rewards.");
39210
+ console.log("");
39211
+ console.log(" Two asks:");
39212
+ console.log(" 1. Use it on real work and keep it installed \u2014 the honest test of");
39213
+ console.log(" whether it earns its place in your terminal.");
39214
+ console.log(" 2. When something breaks or annoys you, tell us: `terminalhire feedback`");
39215
+ console.log(" (2 minutes, goes straight to the founder).");
39216
+ console.log("");
39217
+ console.log(" Four rewards:");
39218
+ console.log(" \u2022 A Founding-Contributor mark on your credential.");
39219
+ console.log(" \u2022 A direct line to the founder \u2014 the person who ships the fix.");
39220
+ console.log(" \u2022 Bounties on the issues your feedback surfaces \u2014 get paid for the");
39221
+ console.log(" rough edges you find.");
39222
+ console.log(" \u2022 A spot on the founding-contributors wall.");
39223
+ console.log("");
39224
+ const join34 = await ask3(' Type "yes" to join the beta as a Founding Contributor (anything else cancels): ');
39225
+ if ((join34 || "").toLowerCase() !== "yes") {
39226
+ console.log("\n No problem \u2014 nothing was sent. Run `terminalhire beta` any time.\n");
39227
+ rl.close();
39228
+ return;
39229
+ }
39230
+ const listAns = await ask3(" List me publicly as a Founding Contributor? [y/N] (Enter = no): ");
39231
+ listPublicly = ["y", "yes"].includes((listAns || "").toLowerCase());
39232
+ } else {
39233
+ console.log("\n You've already opted in to the Terminalhire beta \u2014 checking your status\u2026");
39132
39234
  }
39133
- const listAns = await ask3(" List me publicly as a Founding Contributor? [y/N] (Enter = no): ");
39134
- const listPublicly = ["y", "yes"].includes((listAns || "").toLowerCase());
39135
39235
  rl.close();
39136
39236
  const cookie = readWebSessionCookie();
39137
39237
  if (!cookie) {
@@ -39141,10 +39241,12 @@ async function run23() {
39141
39241
  }
39142
39242
  let res;
39143
39243
  try {
39144
- res = await fetch(`${API_BASE}/api/beta/join`, {
39244
+ res = await fetch(`${API_BASE2}/api/beta/join`, {
39145
39245
  method: "POST",
39146
- headers: { "Content-Type": "application/json", Cookie: `${GH_SESSION_COOKIE8}=${cookie}` },
39147
- body: JSON.stringify({ listPublicly }),
39246
+ headers: { "Content-Type": "application/json", Cookie: `${GH_SESSION_COOKIE9}=${cookie}` },
39247
+ // First run: the prompt-gathered consent. Re-run: the CONSTANT empty body —
39248
+ // a status re-check that carries no user-authored data (see RERUN_STATUS_BODY).
39249
+ body: JSON.stringify(alreadyActed ? RERUN_STATUS_BODY : { listPublicly }),
39148
39250
  signal: AbortSignal.timeout(1e4)
39149
39251
  });
39150
39252
  } catch (err) {
@@ -39153,41 +39255,47 @@ async function run23() {
39153
39255
  `);
39154
39256
  return;
39155
39257
  }
39156
- if (res.status === 401) {
39157
- console.log("\n Your linked web session expired.");
39258
+ if (res.status === 401 || res.status === 403) {
39259
+ console.log("\n Your linked web session isn't valid anymore.");
39158
39260
  console.log(" Run `terminalhire link` to reconnect this terminal, then re-run.\n");
39159
39261
  return;
39160
39262
  }
39161
- if (res.status === 403) {
39162
- console.log("\n The beta is invite-only right now \u2014 your GitHub login is not on the");
39163
- console.log(" Founding-Contributor allowlist yet. Hang tight; it opens wider soon.\n");
39164
- return;
39165
- }
39166
- if (!res.ok) {
39263
+ if (res.status !== 200 && res.status !== 202) {
39167
39264
  console.error(`
39168
39265
  Request failed: /api/beta/join returned ${res.status}.
39169
39266
  `);
39170
39267
  return;
39171
39268
  }
39269
+ let status;
39172
39270
  let memberNo;
39173
39271
  try {
39174
39272
  const data = await res.json();
39273
+ status = typeof data.status === "string" ? data.status : null;
39175
39274
  memberNo = typeof data.memberNo === "number" ? data.memberNo : null;
39176
39275
  } catch {
39177
39276
  }
39277
+ if (status !== "active" && status !== "requested") {
39278
+ status = res.status === 202 ? "requested" : "active";
39279
+ }
39178
39280
  writeConfig({ betaOptIn: true });
39281
+ if (status === "requested") {
39282
+ console.log("\n \u2713 You're on the list.");
39283
+ console.log(" Invites go out in small batches \u2014 run `terminalhire beta` anytime to check your status.\n");
39284
+ return;
39285
+ }
39179
39286
  console.log(`
39180
39287
  \u2713 Founding Contributor${memberNo !== null && memberNo !== void 0 ? ` #${memberNo}` : ""}`);
39181
39288
  console.log(" Leave feedback any time: terminalhire feedback\n");
39182
39289
  }
39183
- var API_BASE, GH_SESSION_COOKIE8;
39290
+ var API_BASE2, GH_SESSION_COOKIE9, RERUN_STATUS_BODY;
39184
39291
  var init_jpi_beta = __esm({
39185
39292
  "bin/jpi-beta.js"() {
39186
39293
  "use strict";
39187
39294
  init_web_session();
39188
39295
  init_config();
39189
- API_BASE = process.env["TERMINALHIRE_API_URL"] || "https://terminalhire.com";
39190
- GH_SESSION_COOKIE8 = "__jpi_gh_session";
39296
+ API_BASE2 = process.env["TERMINALHIRE_API_URL"] || "https://terminalhire.com";
39297
+ GH_SESSION_COOKIE9 = "__jpi_gh_session";
39298
+ RERUN_STATUS_BODY = {};
39191
39299
  }
39192
39300
  });
39193
39301
 
@@ -39196,15 +39304,15 @@ var jpi_feedback_exports = {};
39196
39304
  __export(jpi_feedback_exports, {
39197
39305
  run: () => run24
39198
39306
  });
39199
- import { createInterface as createInterface14 } from "readline";
39200
- import { readFileSync as readFileSync28, existsSync as existsSync20 } from "fs";
39201
- import { join as join31 } from "path";
39202
- import { fileURLToPath as fileURLToPath7 } from "url";
39203
- function readLocalVersion2() {
39307
+ import { createInterface as createInterface15 } from "readline";
39308
+ import { readFileSync as readFileSync29, existsSync as existsSync21 } from "fs";
39309
+ import { join as join32 } from "path";
39310
+ import { fileURLToPath as fileURLToPath8 } from "url";
39311
+ function readLocalVersion3() {
39204
39312
  try {
39205
- for (const p of [join31(__dirname6, "..", "..", "package.json"), join31(__dirname6, "..", "package.json")]) {
39206
- if (existsSync20(p)) {
39207
- const pkg = JSON.parse(readFileSync28(p, "utf8"));
39313
+ for (const p of [join32(__dirname7, "..", "..", "package.json"), join32(__dirname7, "..", "package.json")]) {
39314
+ if (existsSync21(p)) {
39315
+ const pkg = JSON.parse(readFileSync29(p, "utf8"));
39208
39316
  if (pkg.version) return pkg.version;
39209
39317
  }
39210
39318
  }
@@ -39213,20 +39321,24 @@ function readLocalVersion2() {
39213
39321
  return null;
39214
39322
  }
39215
39323
  async function run24() {
39216
- const rl = createInterface14({ input: process.stdin, output: process.stdout });
39324
+ const rl = createInterface15({ input: process.stdin, output: process.stdout });
39217
39325
  const ask3 = (question) => new Promise((resolve2) => {
39218
- let answered = false;
39326
+ const onClose = () => resolve2(null);
39327
+ rl.once("close", onClose);
39219
39328
  rl.question(question, (answer) => {
39220
- answered = true;
39329
+ rl.removeListener("close", onClose);
39221
39330
  resolve2((answer || "").trim());
39222
39331
  });
39223
- rl.once("close", () => {
39224
- if (!answered) resolve2(null);
39225
- });
39226
39332
  });
39333
+ const lastFull = readConfig().lastFullFeedbackAt;
39334
+ const fullDue = !lastFull || Date.now() - Date.parse(lastFull) >= FULL_FORM_INTERVAL_MS;
39335
+ const fullForm = process.argv.includes("--full") || fullDue;
39227
39336
  console.log("");
39228
39337
  console.log(" terminalhire feedback \u2014 goes straight to the founder. Everything below is");
39229
39338
  console.log(" what YOU type; the only thing auto-attached is your CLI version + OS.");
39339
+ if (!fullForm) {
39340
+ console.log(" (quick form \u2014 run `terminalhire feedback --full` for ratings + the long form)");
39341
+ }
39230
39342
  console.log("");
39231
39343
  console.log(" What is this about?");
39232
39344
  CATEGORY_LABELS.forEach((label, i) => console.log(` ${i + 1}) ${label}`));
@@ -39240,22 +39352,26 @@ async function run24() {
39240
39352
  const category = CATEGORIES[catIdx - 1];
39241
39353
  const tryingToDo = await ask3(" What were you trying to do? (Enter to skip): ");
39242
39354
  const expectedVsActual = await ask3(" What did you expect vs. what happened? (Enter to skip): ");
39243
- console.log(" Rate 1\u20135 (Enter to skip any):");
39244
39355
  const ratings = {};
39245
- for (const key of RATING_KEYS) {
39246
- const ans = await ask3(` ${key}: `);
39247
- const n = Number.parseInt(ans || "", 10);
39248
- if (n >= 1 && n <= 5) ratings[key] = n;
39356
+ let almostQuit = null;
39357
+ let keepInstalled = null;
39358
+ if (fullForm) {
39359
+ console.log(" Rate 1\u20135 (Enter to skip any):");
39360
+ for (const key of RATING_KEYS) {
39361
+ const ans = await ask3(` ${key}: `);
39362
+ const n = Number.parseInt(ans || "", 10);
39363
+ if (n >= 1 && n <= 5) ratings[key] = n;
39364
+ }
39365
+ almostQuit = await ask3(" What almost made you quit / uninstall? (Enter to skip): ");
39366
+ keepInstalled = await ask3(" Will you keep it installed? y/n + why (Enter to skip): ");
39249
39367
  }
39250
- const almostQuit = await ask3(" What almost made you quit / uninstall? (Enter to skip): ");
39251
- const keepInstalled = await ask3(" Will you keep it installed? y/n + why (Enter to skip): ");
39252
39368
  const payload = { category };
39253
39369
  if (tryingToDo) payload.tryingToDo = tryingToDo;
39254
39370
  if (expectedVsActual) payload.expectedVsActual = expectedVsActual;
39255
39371
  if (Object.keys(ratings).length > 0) payload.ratings = ratings;
39256
39372
  if (almostQuit) payload.almostQuit = almostQuit;
39257
39373
  if (keepInstalled) payload.keepInstalled = keepInstalled;
39258
- const cliVersion = readLocalVersion2();
39374
+ const cliVersion = readLocalVersion3();
39259
39375
  if (cliVersion) payload.cliVersion = cliVersion;
39260
39376
  payload.os = process.platform;
39261
39377
  console.log("");
@@ -39277,9 +39393,9 @@ async function run24() {
39277
39393
  }
39278
39394
  let res;
39279
39395
  try {
39280
- res = await fetch(`${API_BASE2}/api/feedback`, {
39396
+ res = await fetch(`${API_BASE3}/api/feedback`, {
39281
39397
  method: "POST",
39282
- headers: { "Content-Type": "application/json", Cookie: `${GH_SESSION_COOKIE9}=${cookie}` },
39398
+ headers: { "Content-Type": "application/json", Cookie: `${GH_SESSION_COOKIE10}=${cookie}` },
39283
39399
  body: JSON.stringify(payload),
39284
39400
  signal: AbortSignal.timeout(1e4)
39285
39401
  });
@@ -39310,16 +39426,19 @@ async function run24() {
39310
39426
  `);
39311
39427
  return;
39312
39428
  }
39429
+ if (fullForm) writeConfig({ lastFullFeedbackAt: (/* @__PURE__ */ new Date()).toISOString() });
39313
39430
  console.log("\n \u2713 Sent \u2014 thank you. This goes straight to the founder.\n");
39314
39431
  }
39315
- var __dirname6, API_BASE2, GH_SESSION_COOKIE9, CATEGORIES, CATEGORY_LABELS, RATING_KEYS;
39432
+ var FULL_FORM_INTERVAL_MS, __dirname7, API_BASE3, GH_SESSION_COOKIE10, CATEGORIES, CATEGORY_LABELS, RATING_KEYS;
39316
39433
  var init_jpi_feedback = __esm({
39317
39434
  "bin/jpi-feedback.js"() {
39318
39435
  "use strict";
39319
39436
  init_web_session();
39320
- __dirname6 = fileURLToPath7(new URL(".", import.meta.url));
39321
- API_BASE2 = process.env["TERMINALHIRE_API_URL"] || "https://terminalhire.com";
39322
- GH_SESSION_COOKIE9 = "__jpi_gh_session";
39437
+ init_config();
39438
+ FULL_FORM_INTERVAL_MS = 7 * 24 * 60 * 60 * 1e3;
39439
+ __dirname7 = fileURLToPath8(new URL(".", import.meta.url));
39440
+ API_BASE3 = process.env["TERMINALHIRE_API_URL"] || "https://terminalhire.com";
39441
+ GH_SESSION_COOKIE10 = "__jpi_gh_session";
39323
39442
  CATEGORIES = ["onboarding", "linking", "match-quality", "claim-pr", "chat", "other"];
39324
39443
  CATEGORY_LABELS = ["onboarding", "linking", "match quality", "claim \u2192 PR", "chat", "other"];
39325
39444
  RATING_KEYS = ["onboarding", "linking", "match", "claim", "chat"];
@@ -39327,19 +39446,19 @@ var init_jpi_feedback = __esm({
39327
39446
  });
39328
39447
 
39329
39448
  // bin/jpi-dispatch.js
39330
- import { fileURLToPath as fileURLToPath8 } from "url";
39331
- import { join as join32 } from "path";
39332
- import { existsSync as existsSync21, readFileSync as readFileSync29 } from "fs";
39333
- var __dirname7 = fileURLToPath8(new URL(".", import.meta.url));
39449
+ import { fileURLToPath as fileURLToPath9 } from "url";
39450
+ import { join as join33 } from "path";
39451
+ import { existsSync as existsSync22, readFileSync as readFileSync30 } from "fs";
39452
+ var __dirname8 = fileURLToPath9(new URL(".", import.meta.url));
39334
39453
  function readPackageVersion() {
39335
39454
  try {
39336
39455
  const candidates = [
39337
- join32(__dirname7, "..", "..", "package.json"),
39338
- join32(__dirname7, "..", "package.json")
39456
+ join33(__dirname8, "..", "..", "package.json"),
39457
+ join33(__dirname8, "..", "package.json")
39339
39458
  ];
39340
39459
  for (const p of candidates) {
39341
- if (existsSync21(p)) {
39342
- const pkg = JSON.parse(readFileSync29(p, "utf8"));
39460
+ if (existsSync22(p)) {
39461
+ const pkg = JSON.parse(readFileSync30(p, "utf8"));
39343
39462
  if (pkg.version) return pkg.version;
39344
39463
  }
39345
39464
  }
@@ -39351,7 +39470,7 @@ var SUBCOMMANDS = ["jobs", "devs", "project", "bounties", "contribute", "claim",
39351
39470
  var firstArg = process.argv[2];
39352
39471
  if (!firstArg && !process.stdin.isTTY) {
39353
39472
  const { default: childProcess } = await import("child_process");
39354
- const nudgeScript = join32(__dirname7, "jpi.js");
39473
+ const nudgeScript = join33(__dirname8, "jpi.js");
39355
39474
  const child = childProcess.spawnSync(process.execPath, [nudgeScript], {
39356
39475
  stdio: ["inherit", "inherit", "inherit"]
39357
39476
  });
@@ -39628,9 +39747,9 @@ if (firstArg === "statusline") {
39628
39747
  console.error("Usage: terminalhire statusline --on | --off");
39629
39748
  process.exit(1);
39630
39749
  }
39631
- const fromDist = join32(__dirname7, "..", "..", "statusline-install.js");
39632
- const fromBin = join32(__dirname7, "..", "statusline-install.js");
39633
- const installer = existsSync21(fromDist) ? fromDist : fromBin;
39750
+ const fromDist = join33(__dirname8, "..", "..", "statusline-install.js");
39751
+ const fromBin = join33(__dirname8, "..", "statusline-install.js");
39752
+ const installer = existsSync22(fromDist) ? fromDist : fromBin;
39634
39753
  const { spawnSync: spawnSync2 } = await import("child_process");
39635
39754
  const child = spawnSync2(
39636
39755
  process.execPath,