terminalhire 0.30.2 → 0.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1039,9 +1039,9 @@ var init_keytar = __esm({
1039
1039
  }
1040
1040
  });
1041
1041
 
1042
- // node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node
1042
+ // node-file:/Users/ericgang/job-placement-inline/.claude/worktrees/agent-a0bc554500876cd51/node_modules/keytar/build/Release/keytar.node
1043
1043
  var require_keytar = __commonJS({
1044
- "node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node"(exports, module) {
1044
+ "node-file:/Users/ericgang/job-placement-inline/.claude/worktrees/agent-a0bc554500876cd51/node_modules/keytar/build/Release/keytar.node"(exports, module) {
1045
1045
  "use strict";
1046
1046
  init_keytar();
1047
1047
  try {
@@ -8152,9 +8152,9 @@ var init_keytar = __esm({
8152
8152
  }
8153
8153
  });
8154
8154
 
8155
- // node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node
8155
+ // node-file:/Users/ericgang/job-placement-inline/.claude/worktrees/agent-a0bc554500876cd51/node_modules/keytar/build/Release/keytar.node
8156
8156
  var require_keytar = __commonJS({
8157
- "node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node"(exports, module) {
8157
+ "node-file:/Users/ericgang/job-placement-inline/.claude/worktrees/agent-a0bc554500876cd51/node_modules/keytar/build/Release/keytar.node"(exports, module) {
8158
8158
  "use strict";
8159
8159
  init_keytar();
8160
8160
  try {
@@ -10078,9 +10078,11 @@ var CONTRIBUTE_SLOTS_THIN = 8;
10078
10078
  var ROLE_STABLE_MAX = 8;
10079
10079
  var ROLE_ROTATE_WINDOW = 60;
10080
10080
  var ROTATE_WINDOW_MS = 5 * 60 * 1e3;
10081
- function rotate(list, now) {
10081
+ var ROLE_HEAD_POOL = 12;
10082
+ var ROLE_HEAD_ROTATE_MS = 60 * 60 * 1e3;
10083
+ function rotate(list, now, windowMs = ROTATE_WINDOW_MS) {
10082
10084
  if (!Array.isArray(list) || list.length === 0) return [];
10083
- const idx = Math.floor(now / ROTATE_WINDOW_MS) % list.length;
10085
+ const idx = Math.floor(now / windowMs) % list.length;
10084
10086
  return [...list.slice(idx), ...list.slice(0, idx)];
10085
10087
  }
10086
10088
  function budgetSlots(results, opts = {}) {
@@ -10113,8 +10115,11 @@ function budgetSlots(results, opts = {}) {
10113
10115
  (r) => r && r.job && r.job.source !== "bounty" && r.job.source !== "contribute"
10114
10116
  );
10115
10117
  const roleStable = Math.min(ROLE_STABLE_MAX, roleSlots);
10116
- const stableRoles = roleMatches.slice(0, roleStable);
10117
- const rotableRoles = roleMatches.slice(roleStable, roleStable + ROLE_ROTATE_WINDOW);
10118
+ const headPoolSize = Math.max(roleStable, ROLE_HEAD_POOL);
10119
+ const headPool = roleMatches.slice(0, headPoolSize);
10120
+ const headIndex = new Map(headPool.map((r, i) => [r, i]));
10121
+ const stableRoles = rotate(headPool, now, ROLE_HEAD_ROTATE_MS).slice(0, roleStable).sort((a, b) => headIndex.get(a) - headIndex.get(b));
10122
+ const rotableRoles = roleMatches.slice(headPoolSize, headPoolSize + ROLE_ROTATE_WINDOW);
10118
10123
  const rotatedRoles = rotate(rotableRoles, now);
10119
10124
  const roleTop = [...stableRoles, ...rotatedRoles].slice(0, roleSlots);
10120
10125
  return { roleTop, bountyTop, contributeTop, interestTop, interestJobTop };
@@ -1039,9 +1039,9 @@ var init_keytar = __esm({
1039
1039
  }
1040
1040
  });
1041
1041
 
1042
- // node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node
1042
+ // node-file:/Users/ericgang/job-placement-inline/.claude/worktrees/agent-a0bc554500876cd51/node_modules/keytar/build/Release/keytar.node
1043
1043
  var require_keytar = __commonJS({
1044
- "node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node"(exports, module) {
1044
+ "node-file:/Users/ericgang/job-placement-inline/.claude/worktrees/agent-a0bc554500876cd51/node_modules/keytar/build/Release/keytar.node"(exports, module) {
1045
1045
  "use strict";
1046
1046
  init_keytar();
1047
1047
  try {
@@ -1039,9 +1039,9 @@ var init_keytar = __esm({
1039
1039
  }
1040
1040
  });
1041
1041
 
1042
- // node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node
1042
+ // node-file:/Users/ericgang/job-placement-inline/.claude/worktrees/agent-a0bc554500876cd51/node_modules/keytar/build/Release/keytar.node
1043
1043
  var require_keytar = __commonJS({
1044
- "node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node"(exports, module) {
1044
+ "node-file:/Users/ericgang/job-placement-inline/.claude/worktrees/agent-a0bc554500876cd51/node_modules/keytar/build/Release/keytar.node"(exports, module) {
1045
1045
  "use strict";
1046
1046
  init_keytar();
1047
1047
  try {
@@ -1918,9 +1918,9 @@ var init_keytar = __esm({
1918
1918
  }
1919
1919
  });
1920
1920
 
1921
- // node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node
1921
+ // node-file:/Users/ericgang/job-placement-inline/.claude/worktrees/agent-a0bc554500876cd51/node_modules/keytar/build/Release/keytar.node
1922
1922
  var require_keytar = __commonJS({
1923
- "node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node"(exports, module) {
1923
+ "node-file:/Users/ericgang/job-placement-inline/.claude/worktrees/agent-a0bc554500876cd51/node_modules/keytar/build/Release/keytar.node"(exports, module) {
1924
1924
  "use strict";
1925
1925
  init_keytar();
1926
1926
  try {
@@ -41,9 +41,9 @@ var init_keytar = __esm({
41
41
  }
42
42
  });
43
43
 
44
- // node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node
44
+ // node-file:/Users/ericgang/job-placement-inline/.claude/worktrees/agent-a0bc554500876cd51/node_modules/keytar/build/Release/keytar.node
45
45
  var require_keytar = __commonJS({
46
- "node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node"(exports, module) {
46
+ "node-file:/Users/ericgang/job-placement-inline/.claude/worktrees/agent-a0bc554500876cd51/node_modules/keytar/build/Release/keytar.node"(exports, module) {
47
47
  "use strict";
48
48
  init_keytar();
49
49
  try {
@@ -41,9 +41,9 @@ var init_keytar = __esm({
41
41
  }
42
42
  });
43
43
 
44
- // node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node
44
+ // node-file:/Users/ericgang/job-placement-inline/.claude/worktrees/agent-a0bc554500876cd51/node_modules/keytar/build/Release/keytar.node
45
45
  var require_keytar = __commonJS({
46
- "node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node"(exports, module) {
46
+ "node-file:/Users/ericgang/job-placement-inline/.claude/worktrees/agent-a0bc554500876cd51/node_modules/keytar/build/Release/keytar.node"(exports, module) {
47
47
  "use strict";
48
48
  init_keytar();
49
49
  try {
@@ -41,9 +41,9 @@ var init_keytar = __esm({
41
41
  }
42
42
  });
43
43
 
44
- // node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node
44
+ // node-file:/Users/ericgang/job-placement-inline/.claude/worktrees/agent-a0bc554500876cd51/node_modules/keytar/build/Release/keytar.node
45
45
  var require_keytar = __commonJS({
46
- "node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node"(exports, module) {
46
+ "node-file:/Users/ericgang/job-placement-inline/.claude/worktrees/agent-a0bc554500876cd51/node_modules/keytar/build/Release/keytar.node"(exports, module) {
47
47
  "use strict";
48
48
  init_keytar();
49
49
  try {
package/dist/src/intro.js CHANGED
@@ -1049,9 +1049,9 @@ var init_keytar = __esm({
1049
1049
  }
1050
1050
  });
1051
1051
 
1052
- // node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node
1052
+ // node-file:/Users/ericgang/job-placement-inline/.claude/worktrees/agent-a0bc554500876cd51/node_modules/keytar/build/Release/keytar.node
1053
1053
  var require_keytar = __commonJS({
1054
- "node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node"(exports, module) {
1054
+ "node-file:/Users/ericgang/job-placement-inline/.claude/worktrees/agent-a0bc554500876cd51/node_modules/keytar/build/Release/keytar.node"(exports, module) {
1055
1055
  "use strict";
1056
1056
  init_keytar();
1057
1057
  try {
@@ -41,9 +41,9 @@ var init_keytar = __esm({
41
41
  }
42
42
  });
43
43
 
44
- // node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node
44
+ // node-file:/Users/ericgang/job-placement-inline/.claude/worktrees/agent-a0bc554500876cd51/node_modules/keytar/build/Release/keytar.node
45
45
  var require_keytar = __commonJS({
46
- "node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node"(exports, module) {
46
+ "node-file:/Users/ericgang/job-placement-inline/.claude/worktrees/agent-a0bc554500876cd51/node_modules/keytar/build/Release/keytar.node"(exports, module) {
47
47
  "use strict";
48
48
  init_keytar();
49
49
  try {
@@ -2,6 +2,7 @@
2
2
  var GH_API = "https://api.github.com";
3
3
  var GH_HEADERS = { "User-Agent": "terminalhire-claim", Accept: "application/vnd.github+json" };
4
4
  var MAX_REQUESTS = 4;
5
+ var POLICY_RULESET_VERSION = 2;
5
6
  var AI_SIGNAL_PATTERNS = [
6
7
  { label: "AI", re: /\bAI\b/i },
7
8
  { label: "artificial intelligence", re: /artificial intelligence/i },
@@ -13,10 +14,41 @@ var AI_SIGNAL_PATTERNS = [
13
14
  { label: "generative", re: /\bgenerative\b/i },
14
15
  { label: "machine-generated", re: /machine[\s-]generated/i }
15
16
  ];
17
+ var AI_TERM = "(?:ai|llms?|generative(?:\\s+ai)?|artificial intelligence|language models?|copilot|chatgpt|claude|machine[\\s-]generated)";
18
+ var PROHIBITED_PATTERNS = [
19
+ new RegExp(`prohibit\\w*[^.\\n]{0,60}\\b${AI_TERM}`, "i"),
20
+ /did not write the code yourself/i,
21
+ new RegExp(`(?:not|never|don'?t|won'?t)\\s+accept\\w*[^.\\n]{0,60}\\b${AI_TERM}`, "i"),
22
+ new RegExp(`\\bno\\s+${AI_TERM}[^.\\n]{0,40}\\b(?:prs?|pull requests?|contributions?|code|patch(?:es)?|commits?|submissions?)\\b`, "i"),
23
+ new RegExp(
24
+ `\\b${AI_TERM}[^.\\n]{0,60}\\b(?:is|are|will be)\\s+(?:\\w+\\s+)?(?:not accepted|not allowed|banned|rejected|removed|closed|reverted|prohibited|forbidden)`,
25
+ "i"
26
+ )
27
+ ];
28
+ var DISCLOSURE_PATTERNS = [
29
+ new RegExp(`disclos\\w+[^.\\n]{0,60}\\b${AI_TERM}`, "i"),
30
+ new RegExp(`\\b${AI_TERM}[^.\\n]{0,60}disclos`, "i"),
31
+ new RegExp(`\\b${AI_TERM}[\\s-]assist\\w*[^.\\n]{0,60}\\b(?:must|should|required?)\\b`, "i"),
32
+ // PR-template checkbox, e.g. "- [ ] I used AI tools and have reviewed the output"
33
+ new RegExp(`\\[ \\][^\\n]{0,80}\\b${AI_TERM}`, "i")
34
+ ];
35
+ var REQUIREMENT_PATTERNS = [
36
+ // `/take` bot first: its docs usually also say "assign", and the bot is the
37
+ // more specific expectation (post exactly `/take`, not a prose request).
38
+ { kind: "take-bot", re: /(?:^|[\s`"'(])\/take\b/m },
39
+ { kind: "assignment-required", re: /(?:request|ask|wait)[^.\n]{0,40}\bassign/i },
40
+ { kind: "assignment-required", re: /\bassigned before\b/i },
41
+ { kind: "assignment-required", re: /\bself[\s-]assign/i },
42
+ { kind: "assignment-required", re: /do not (?:open|submit)[^.\n]{0,40}\b(?:prs?|pull requests?)\b/i },
43
+ { kind: "cla-required", re: /\bCLA\b/ },
44
+ { kind: "cla-required", re: /contributor licen[cs]e agreement/i },
45
+ { kind: "discussion-first", re: /open an issue (?:first|before)/i },
46
+ { kind: "discussion-first", re: /discuss\w*[^.\n]{0,40}\bbefore\b/i }
47
+ ];
16
48
  var CANDIDATE_GROUPS = [
17
49
  ["CONTRIBUTING.md", ".github/CONTRIBUTING.md", "docs/CONTRIBUTING.md"],
18
- [".github/PULL_REQUEST_TEMPLATE.md", "PULL_REQUEST_TEMPLATE.md"],
19
- ["AGENTS.md"]
50
+ ["AGENTS.md", "AGENTS.MD"],
51
+ [".github/PULL_REQUEST_TEMPLATE.md", "PULL_REQUEST_TEMPLATE.md"]
20
52
  ];
21
53
  async function fetchContentsFile(fetchImpl, repoFullName, path) {
22
54
  try {
@@ -37,23 +69,55 @@ async function fetchContentsFile(fetchImpl, repoFullName, path) {
37
69
  return { ok: false, missing: false, content: null };
38
70
  }
39
71
  }
40
- function findHits(file, content) {
41
- const lines = content.split("\n");
72
+ function classifyLine(line) {
73
+ if (PROHIBITED_PATTERNS.some((re) => re.test(line))) return "prohibited";
74
+ if (DISCLOSURE_PATTERNS.some((re) => re.test(line))) return "disclosure-required";
75
+ if (AI_SIGNAL_PATTERNS.some((p) => p.re.test(line))) return "ai-mentioned";
76
+ return null;
77
+ }
78
+ var VERDICT_SEVERITY = {
79
+ "ai-mentioned": 1,
80
+ "disclosure-required": 2,
81
+ prohibited: 3
82
+ };
83
+ function sanitizeExcerpt(text) {
84
+ return text.replace(/[\x00-\x08\x0B-\x1F\x7F-\x9F]/g, "");
85
+ }
86
+ function excerptAround(lines, i) {
87
+ const start = Math.max(0, i - 2);
88
+ const end = Math.min(lines.length, i + 3);
89
+ return sanitizeExcerpt(lines.slice(start, end).join("\n"));
90
+ }
91
+ function auditContent(files) {
42
92
  const hits = [];
43
- for (let i = 0; i < lines.length; i++) {
44
- const line = lines[i];
45
- if (!AI_SIGNAL_PATTERNS.some((p) => p.re.test(line))) continue;
46
- const start = Math.max(0, i - 2);
47
- const end = Math.min(lines.length, i + 3);
48
- hits.push({ file, excerpt: lines.slice(start, end).join("\n") });
93
+ const requirements = [];
94
+ const seenKinds = /* @__PURE__ */ new Set();
95
+ for (const { file, content } of files) {
96
+ const lines = content.split("\n");
97
+ for (let i = 0; i < lines.length; i++) {
98
+ const rule = classifyLine(lines[i]);
99
+ if (rule) hits.push({ file, excerpt: excerptAround(lines, i), rule });
100
+ for (const { kind, re } of REQUIREMENT_PATTERNS) {
101
+ if (seenKinds.has(kind) || !re.test(lines[i])) continue;
102
+ seenKinds.add(kind);
103
+ requirements.push({ kind, file, excerpt: excerptAround(lines, i) });
104
+ }
105
+ }
106
+ }
107
+ let verdict = "clean";
108
+ for (const h of hits) {
109
+ if (verdict === "clean" || VERDICT_SEVERITY[h.rule] > VERDICT_SEVERITY[verdict]) {
110
+ verdict = h.rule;
111
+ }
49
112
  }
50
- return hits;
113
+ const assignment = seenKinds.has("take-bot") ? "take-bot" : seenKinds.has("assignment-required") ? "required" : "none";
114
+ return { hits, requirements, verdict, assignment };
51
115
  }
52
116
  async function checkRepoPolicy(repoFullName, opts = {}) {
53
117
  const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
54
118
  let requestsUsed = 0;
55
119
  let hadError = false;
56
- const hits = [];
120
+ const files = [];
57
121
  outer: for (const group of CANDIDATE_GROUPS) {
58
122
  for (const path of group) {
59
123
  if (requestsUsed >= MAX_REQUESTS) break outer;
@@ -64,14 +128,21 @@ async function checkRepoPolicy(repoFullName, opts = {}) {
64
128
  continue;
65
129
  }
66
130
  if (outcome.missing) continue;
67
- if (outcome.content) hits.push(...findHits(path, outcome.content));
131
+ if (outcome.content) files.push({ file: path, content: outcome.content });
68
132
  break;
69
133
  }
70
134
  }
71
- if (hits.length > 0) return { status: "flagged", hits };
72
- if (hadError) return { status: "unavailable", hits: [] };
73
- return { status: "clean", hits: [] };
135
+ const { hits, requirements, verdict, assignment } = auditContent(files);
136
+ if (hits.length > 0) {
137
+ return { status: "flagged", verdict, hits, requirements, assignment, rulesetVersion: POLICY_RULESET_VERSION };
138
+ }
139
+ if (hadError) {
140
+ return { status: "unavailable", verdict: "unavailable", hits: [], requirements, assignment, rulesetVersion: POLICY_RULESET_VERSION };
141
+ }
142
+ return { status: "clean", verdict: "clean", hits: [], requirements, assignment, rulesetVersion: POLICY_RULESET_VERSION };
74
143
  }
75
144
  export {
145
+ POLICY_RULESET_VERSION,
146
+ auditContent,
76
147
  checkRepoPolicy
77
148
  };
@@ -1365,9 +1365,9 @@ var init_keytar = __esm({
1365
1365
  }
1366
1366
  });
1367
1367
 
1368
- // node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node
1368
+ // node-file:/Users/ericgang/job-placement-inline/.claude/worktrees/agent-a0bc554500876cd51/node_modules/keytar/build/Release/keytar.node
1369
1369
  var require_keytar = __commonJS({
1370
- "node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node"(exports, module) {
1370
+ "node-file:/Users/ericgang/job-placement-inline/.claude/worktrees/agent-a0bc554500876cd51/node_modules/keytar/build/Release/keytar.node"(exports, module) {
1371
1371
  "use strict";
1372
1372
  init_keytar();
1373
1373
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "terminalhire",
3
- "version": "0.30.2",
3
+ "version": "0.32.0",
4
4
  "description": "Local-first job matching for developers — ambient job matches in the Claude Code spinner. Matching runs on your machine; your profile never leaves it.",
5
5
  "repository": {
6
6
  "type": "git",