terminalhire 0.2.5 → 0.3.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.
@@ -16,221 +16,347 @@ var init_types = __esm({
16
16
  }
17
17
  });
18
18
 
19
- // ../../packages/core/src/vocabulary.ts
19
+ // ../../packages/core/src/vocab/graph.data.ts
20
+ var VOCAB_NODES;
21
+ var init_graph_data = __esm({
22
+ "../../packages/core/src/vocab/graph.data.ts"() {
23
+ "use strict";
24
+ VOCAB_NODES = [
25
+ // ── Languages ─────────────────────────────────────────────────────────────
26
+ { id: "javascript", synonyms: ["js"], related: [{ to: "typescript", w: 0.6 }] },
27
+ { id: "typescript", parents: ["javascript"], synonyms: ["ts"] },
28
+ { id: "python", synonyms: ["py"] },
29
+ { id: "go", synonyms: ["golang"] },
30
+ { id: "rust" },
31
+ { id: "java", related: [{ to: "kotlin", w: 0.45 }, { to: "scala", w: 0.4 }] },
32
+ { id: "ruby" },
33
+ { id: "elixir" },
34
+ { id: "scala", related: [{ to: "java", w: 0.4 }] },
35
+ { id: "kotlin", related: [{ to: "java", w: 0.45 }] },
36
+ { id: "swift" },
37
+ { id: "cpp", synonyms: ["c++"] },
38
+ { id: "csharp", synonyms: ["c#"] },
39
+ { id: "php" },
40
+ { id: "haskell" },
41
+ { id: "clojure" },
42
+ { id: "r" },
43
+ { id: "dart" },
44
+ // ── Frontend ──────────────────────────────────────────────────────────────
45
+ {
46
+ id: "react",
47
+ parents: ["javascript"],
48
+ synonyms: ["reactjs"],
49
+ related: [{ to: "nextjs", w: 0.55 }, { to: "vue", w: 0.4 }, { to: "svelte", w: 0.4 }, { to: "solidjs", w: 0.5 }, { to: "angular", w: 0.35 }]
50
+ },
51
+ { id: "nextjs", parents: ["react"], synonyms: ["next", "next.js"], related: [{ to: "remix", w: 0.5 }] },
52
+ { id: "vue", parents: ["javascript"], synonyms: ["vue.js"], related: [{ to: "nuxt", w: 0.6 }] },
53
+ { id: "nuxt", parents: ["vue"], synonyms: ["nuxt.js"] },
54
+ { id: "svelte", parents: ["javascript"], related: [{ to: "sveltekit", w: 0.65 }] },
55
+ { id: "sveltekit", parents: ["svelte"] },
56
+ { id: "angular", parents: ["typescript"], synonyms: ["angular.js", "angularjs"] },
57
+ { id: "solidjs", parents: ["javascript"] },
58
+ { id: "remix", parents: ["react"], synonyms: ["remix.run"] },
59
+ { id: "astro", parents: ["javascript"], related: [{ to: "nextjs", w: 0.4 }] },
60
+ { id: "qwik", parents: ["javascript"] },
61
+ { id: "tailwind", parents: ["css"], synonyms: ["tailwindcss", "tw"] },
62
+ { id: "css" },
63
+ { id: "html" },
64
+ { id: "redux", parents: ["react"] },
65
+ { id: "vite", parents: ["frontend"] },
66
+ { id: "webpack", parents: ["frontend"] },
67
+ { id: "storybook", parents: ["frontend"] },
68
+ // ── Backend frameworks / runtimes ───────────────────────────────────────────
69
+ {
70
+ id: "nodejs",
71
+ parents: ["javascript"],
72
+ synonyms: ["node", "node.js"],
73
+ related: [{ to: "express", w: 0.5 }, { to: "fastify", w: 0.45 }, { to: "nestjs", w: 0.45 }]
74
+ },
75
+ { id: "express", parents: ["nodejs"], synonyms: ["express.js", "expressjs"], related: [{ to: "fastify", w: 0.5 }] },
76
+ { id: "fastify", parents: ["nodejs"] },
77
+ { id: "nestjs", parents: ["nodejs"], synonyms: ["nest", "nest.js"] },
78
+ { id: "hono", parents: ["nodejs"] },
79
+ { id: "deno", parents: ["javascript"], related: [{ to: "nodejs", w: 0.5 }, { to: "bun", w: 0.5 }] },
80
+ { id: "bun", parents: ["javascript"], related: [{ to: "nodejs", w: 0.5 }] },
81
+ { id: "django", parents: ["python"], related: [{ to: "flask", w: 0.5 }, { to: "fastapi", w: 0.45 }] },
82
+ { id: "fastapi", parents: ["python"], related: [{ to: "flask", w: 0.55 }, { to: "django", w: 0.45 }] },
83
+ { id: "flask", parents: ["python"] },
84
+ { id: "rails", parents: ["ruby"], synonyms: ["ruby-on-rails", "ror"] },
85
+ { id: "spring", parents: ["java"], synonyms: ["spring-boot", "springboot"] },
86
+ { id: "actix", parents: ["rust"] },
87
+ { id: "gin", parents: ["go"] },
88
+ { id: "phoenix", parents: ["elixir"] },
89
+ { id: "laravel", parents: ["php"] },
90
+ { id: "dotnet", parents: ["csharp"], synonyms: [".net", "asp.net", "dotnet-core"] },
91
+ // ── Infrastructure & DevOps ─────────────────────────────────────────────────
92
+ { id: "kubernetes", synonyms: ["k8s", "kube"], related: [{ to: "docker", w: 0.5 }, { to: "helm", w: 0.55 }, { to: "terraform", w: 0.4 }, { to: "argocd", w: 0.45 }] },
93
+ { id: "docker", parents: ["devops"], related: [{ to: "kubernetes", w: 0.5 }] },
94
+ { id: "terraform", synonyms: ["tf"], related: [{ to: "pulumi", w: 0.55 }, { to: "ansible", w: 0.4 }, { to: "aws", w: 0.4 }] },
95
+ { id: "pulumi", related: [{ to: "terraform", w: 0.55 }] },
96
+ { id: "ansible" },
97
+ { id: "aws", synonyms: ["amazon-web-services"], related: [{ to: "gcp", w: 0.4 }, { to: "azure", w: 0.4 }] },
98
+ { id: "gcp", synonyms: ["google-cloud", "google-cloud-platform"], related: [{ to: "aws", w: 0.4 }, { to: "azure", w: 0.4 }] },
99
+ { id: "azure", synonyms: ["microsoft-azure"], related: [{ to: "aws", w: 0.4 }] },
100
+ { id: "ci-cd", synonyms: ["cicd", "jenkins", "circleci", "circle-ci", "travis"], related: [{ to: "github-actions", w: 0.6 }, { to: "gitlab-ci", w: 0.6 }] },
101
+ { id: "github-actions", parents: ["ci-cd"], synonyms: ["github-action"] },
102
+ { id: "gitlab-ci", parents: ["ci-cd"], synonyms: ["gitlab"] },
103
+ { id: "linux" },
104
+ { id: "nginx" },
105
+ { id: "prometheus", parents: ["observability"], related: [{ to: "grafana", w: 0.6 }] },
106
+ { id: "grafana", parents: ["observability"] },
107
+ { id: "datadog", parents: ["observability"] },
108
+ { id: "opentelemetry", parents: ["observability"], synonyms: ["otel"] },
109
+ { id: "vercel", related: [{ to: "netlify", w: 0.5 }, { to: "nextjs", w: 0.4 }] },
110
+ { id: "netlify" },
111
+ { id: "fly", synonyms: ["fly.io"], related: [{ to: "railway", w: 0.5 }, { to: "render", w: 0.5 }] },
112
+ { id: "railway", related: [{ to: "render", w: 0.5 }] },
113
+ { id: "render" },
114
+ { id: "cloudflare", synonyms: ["cloudflare-workers"] },
115
+ { id: "helm", parents: ["kubernetes"] },
116
+ { id: "argocd", parents: ["kubernetes"] },
117
+ { id: "serverless", parents: ["devops"] },
118
+ // ── Databases & storage ─────────────────────────────────────────────────────
119
+ { id: "postgresql", synonyms: ["postgres", "pg"], related: [{ to: "mysql", w: 0.45 }, { to: "sqlite", w: 0.4 }] },
120
+ { id: "mysql", related: [{ to: "postgresql", w: 0.45 }] },
121
+ { id: "sqlite" },
122
+ { id: "mongodb", synonyms: ["mongo"] },
123
+ { id: "redis", related: [{ to: "caching", w: 0.5 }] },
124
+ { id: "elasticsearch", synonyms: ["elastic"], related: [{ to: "search", w: 0.55 }] },
125
+ { id: "kafka", synonyms: ["apache-kafka"], related: [{ to: "rabbitmq", w: 0.5 }, { to: "message-queue", w: 0.55 }] },
126
+ { id: "rabbitmq", related: [{ to: "message-queue", w: 0.55 }] },
127
+ { id: "cassandra" },
128
+ { id: "dynamodb", parents: ["aws"] },
129
+ { id: "snowflake", parents: ["data-engineering"], related: [{ to: "clickhouse", w: 0.4 }] },
130
+ { id: "clickhouse", parents: ["data-engineering"], related: [{ to: "duckdb", w: 0.35 }] },
131
+ { id: "duckdb", parents: ["data-engineering"] },
132
+ { id: "supabase", related: [{ to: "postgresql", w: 0.5 }, { to: "neon", w: 0.4 }] },
133
+ { id: "planetscale", related: [{ to: "mysql", w: 0.5 }] },
134
+ { id: "neon", related: [{ to: "postgresql", w: 0.5 }] },
135
+ { id: "turso", related: [{ to: "sqlite", w: 0.5 }] },
136
+ { id: "cockroachdb", related: [{ to: "postgresql", w: 0.45 }] },
137
+ { id: "prisma", parents: ["backend"], synonyms: ["@prisma/client"], related: [{ to: "drizzle", w: 0.5 }, { to: "typeorm", w: 0.45 }, { to: "sequelize", w: 0.4 }] },
138
+ { id: "drizzle", synonyms: ["drizzle-orm"], related: [{ to: "prisma", w: 0.5 }] },
139
+ { id: "sequelize", related: [{ to: "typeorm", w: 0.4 }] },
140
+ { id: "typeorm", related: [{ to: "prisma", w: 0.45 }] },
141
+ { id: "sqlalchemy", parents: ["python"] },
142
+ // ── Data engineering & ML ───────────────────────────────────────────────────
143
+ { id: "data-engineering", synonyms: ["data-eng"], related: [{ to: "spark", w: 0.5 }, { to: "airflow", w: 0.5 }, { to: "dbt", w: 0.45 }] },
144
+ { id: "spark", parents: ["data-engineering"], synonyms: ["apache-spark"] },
145
+ { id: "airflow", parents: ["data-engineering"], synonyms: ["apache-airflow"] },
146
+ { id: "dbt", parents: ["data-engineering"] },
147
+ { id: "ml", synonyms: ["machine-learning"], related: [{ to: "pytorch", w: 0.5 }, { to: "tensorflow", w: 0.5 }, { to: "scikit-learn", w: 0.5 }] },
148
+ { id: "llm", parents: ["ml"], synonyms: ["llms", "genai", "generative-ai"], related: [{ to: "langchain", w: 0.5 }, { to: "rag", w: 0.55 }, { to: "openai", w: 0.45 }, { to: "anthropic", w: 0.45 }] },
149
+ { id: "pytorch", parents: ["ml"], synonyms: ["torch"], related: [{ to: "tensorflow", w: 0.5 }] },
150
+ { id: "tensorflow", parents: ["ml"], synonyms: ["keras", "tf-keras"] },
151
+ { id: "pandas", parents: ["python"], related: [{ to: "numpy", w: 0.6 }] },
152
+ { id: "numpy", parents: ["python"] },
153
+ { id: "scikit-learn", parents: ["ml"], synonyms: ["sklearn"] },
154
+ { id: "jupyter", parents: ["python"] },
155
+ { id: "langchain", parents: ["llm"], synonyms: ["llamaindex"] },
156
+ { id: "huggingface", parents: ["ml"], synonyms: ["hugging-face"] },
157
+ { id: "openai", parents: ["llm"] },
158
+ { id: "anthropic", parents: ["llm"], synonyms: ["claude"] },
159
+ { id: "rag", parents: ["llm"], synonyms: ["retrieval-augmented-generation"] },
160
+ { id: "mlops", parents: ["ml"], related: [{ to: "devops", w: 0.4 }] },
161
+ // ── Mobile ──────────────────────────────────────────────────────────────────
162
+ { id: "mobile", related: [{ to: "ios", w: 0.5 }, { to: "android", w: 0.5 }] },
163
+ { id: "ios", parents: ["mobile", "swift"], related: [{ to: "android", w: 0.4 }] },
164
+ { id: "android", parents: ["mobile"], related: [{ to: "kotlin", w: 0.4 }] },
165
+ { id: "swiftui", parents: ["ios", "swift"] },
166
+ { id: "react-native", parents: ["mobile", "react"], synonyms: ["reactnative"], related: [{ to: "flutter", w: 0.4 }, { to: "expo", w: 0.6 }] },
167
+ { id: "flutter", parents: ["mobile", "dart"] },
168
+ { id: "expo", parents: ["react-native"] },
169
+ { id: "kotlin-multiplatform", parents: ["mobile", "kotlin"], synonyms: ["kmp"] },
170
+ // ── Domains / capabilities ──────────────────────────────────────────────────
171
+ { id: "frontend", related: [{ to: "react", w: 0.4 }, { to: "css", w: 0.3 }] },
172
+ { id: "backend", related: [{ to: "api-design", w: 0.4 }, { to: "microservices", w: 0.4 }] },
173
+ { id: "devops", related: [{ to: "kubernetes", w: 0.4 }, { to: "ci-cd", w: 0.4 }, { to: "docker", w: 0.4 }] },
174
+ { id: "authentication", synonyms: ["auth", "jwt", "saml", "passport", "auth0", "clerk", "nextauth"], related: [{ to: "oauth", w: 0.6 }, { to: "security", w: 0.5 }] },
175
+ { id: "oauth", parents: ["authentication"], synonyms: ["oauth2", "oidc"], related: [{ to: "security", w: 0.4 }] },
176
+ { id: "security", related: [{ to: "authentication", w: 0.5 }] },
177
+ { id: "payments", synonyms: ["stripe", "braintree", "paddle", "lemonsqueezy", "@stripe/stripe-js"], related: [{ to: "billing", w: 0.6 }] },
178
+ { id: "billing", synonyms: ["recurly", "chargebee"] },
179
+ { id: "api-design", synonyms: ["rest", "restful", "rest-api"], related: [{ to: "graphql", w: 0.4 }, { to: "grpc", w: 0.4 }, { to: "backend", w: 0.4 }] },
180
+ { id: "graphql", synonyms: ["gql"], related: [{ to: "trpc", w: 0.4 }] },
181
+ { id: "trpc", related: [{ to: "graphql", w: 0.4 }] },
182
+ { id: "grpc", synonyms: ["grpc-web"], related: [{ to: "microservices", w: 0.3 }] },
183
+ { id: "microservices" },
184
+ { id: "websockets", synonyms: ["ws", "socket.io"], related: [{ to: "realtime", w: 0.6 }] },
185
+ { id: "realtime", synonyms: ["real-time"] },
186
+ { id: "message-queue", synonyms: ["mq"] },
187
+ { id: "caching", synonyms: ["cache"] },
188
+ { id: "search", synonyms: ["full-text-search"] },
189
+ { id: "observability", synonyms: ["o11y"], related: [{ to: "monitoring", w: 0.6 }] },
190
+ { id: "monitoring", related: [{ to: "prometheus", w: 0.4 }] },
191
+ { id: "testing", related: [{ to: "unit-testing", w: 0.5 }, { to: "e2e-testing", w: 0.5 }] },
192
+ { id: "unit-testing", parents: ["testing"] },
193
+ { id: "e2e-testing", parents: ["testing"], synonyms: ["e2e", "end-to-end-testing"] },
194
+ { id: "jest", parents: ["testing"], related: [{ to: "vitest", w: 0.6 }, { to: "mocha", w: 0.5 }] },
195
+ { id: "vitest", parents: ["testing"], related: [{ to: "jest", w: 0.6 }] },
196
+ { id: "playwright", parents: ["e2e-testing"], related: [{ to: "cypress", w: 0.6 }] },
197
+ { id: "cypress", parents: ["e2e-testing"] },
198
+ { id: "mocha", parents: ["testing"] },
199
+ { id: "pytest", parents: ["testing", "python"] },
200
+ { id: "accessibility", synonyms: ["a11y"] },
201
+ { id: "seo" },
202
+ { id: "performance", synonyms: ["perf", "web-performance"] }
203
+ ];
204
+ }
205
+ });
206
+
207
+ // ../../packages/core/src/vocab/closure.ts
208
+ function round3(n) {
209
+ return Math.round(n * 1e3) / 1e3;
210
+ }
211
+ function validateGraph(nodes) {
212
+ const ids = /* @__PURE__ */ new Set();
213
+ for (const n of nodes) {
214
+ if (ids.has(n.id)) throw new Error(`vocab: duplicate id "${n.id}"`);
215
+ ids.add(n.id);
216
+ }
217
+ const seenAlias = /* @__PURE__ */ new Map();
218
+ for (const n of nodes) {
219
+ for (const p of n.parents ?? []) {
220
+ if (p === n.id) throw new Error(`vocab: "${n.id}" lists itself as a parent`);
221
+ if (!ids.has(p)) throw new Error(`vocab: "${n.id}" parent "${p}" is not a defined id`);
222
+ }
223
+ for (const e of n.related ?? []) {
224
+ if (e.to === n.id) throw new Error(`vocab: "${n.id}" relates to itself`);
225
+ if (!ids.has(e.to)) throw new Error(`vocab: "${n.id}" related "${e.to}" is not a defined id`);
226
+ if (!(e.w > 0 && e.w <= 1)) throw new Error(`vocab: "${n.id}"\u2192"${e.to}" weight ${e.w} out of (0,1]`);
227
+ }
228
+ for (const s of n.synonyms ?? []) {
229
+ const alias = s.toLowerCase();
230
+ if (ids.has(alias)) throw new Error(`vocab: synonym "${alias}" collides with a canonical id`);
231
+ const prev = seenAlias.get(alias);
232
+ if (prev && prev !== n.id) throw new Error(`vocab: synonym "${alias}" maps to both "${prev}" and "${n.id}"`);
233
+ seenAlias.set(alias, n.id);
234
+ }
235
+ }
236
+ const visiting = /* @__PURE__ */ new Set();
237
+ const done = /* @__PURE__ */ new Set();
238
+ const parentMap = new Map(nodes.map((n) => [n.id, n.parents ?? []]));
239
+ const walk = (id, path) => {
240
+ if (done.has(id)) return;
241
+ if (visiting.has(id)) throw new Error(`vocab: parent cycle ${[...path, id].join(" \u2192 ")}`);
242
+ visiting.add(id);
243
+ for (const p of parentMap.get(id) ?? []) walk(p, [...path, id]);
244
+ visiting.delete(id);
245
+ done.add(id);
246
+ };
247
+ for (const n of nodes) walk(n.id, []);
248
+ }
249
+ function buildAdjacency(nodes) {
250
+ const adj = /* @__PURE__ */ new Map();
251
+ const add = (from, to, w) => {
252
+ let m = adj.get(from);
253
+ if (!m) adj.set(from, m = /* @__PURE__ */ new Map());
254
+ if (w > (m.get(to) ?? 0)) m.set(to, w);
255
+ };
256
+ for (const n of nodes) {
257
+ for (const p of n.parents ?? []) {
258
+ add(n.id, p, PARENT_UP);
259
+ add(p, n.id, PARENT_DOWN);
260
+ }
261
+ for (const e of n.related ?? []) {
262
+ add(n.id, e.to, e.w);
263
+ add(e.to, n.id, e.w);
264
+ }
265
+ }
266
+ return adj;
267
+ }
268
+ function closureFrom(source, adj) {
269
+ const best = /* @__PURE__ */ new Map();
270
+ for (const [t, w] of adj.get(source) ?? []) {
271
+ if (w >= DECAY_FLOOR) best.set(t, { w: round3(w), via: t });
272
+ }
273
+ const settled = /* @__PURE__ */ new Set([source]);
274
+ while (true) {
275
+ let u;
276
+ let uw = 0;
277
+ for (const [t, e] of best) {
278
+ if (!settled.has(t) && e.w > uw) {
279
+ u = t;
280
+ uw = e.w;
281
+ }
282
+ }
283
+ if (!u) break;
284
+ settled.add(u);
285
+ const via = best.get(u).via;
286
+ for (const [t, we] of adj.get(u) ?? []) {
287
+ if (settled.has(t)) continue;
288
+ const cand = round3(uw * we);
289
+ if (cand >= DECAY_FLOOR && cand > (best.get(t)?.w ?? 0)) {
290
+ best.set(t, { w: cand, via });
291
+ }
292
+ }
293
+ }
294
+ best.delete(source);
295
+ return best;
296
+ }
297
+ function buildGraph(nodes) {
298
+ validateGraph(nodes);
299
+ const ids = new Set(nodes.map((n) => n.id));
300
+ const synonyms = /* @__PURE__ */ new Map();
301
+ for (const n of nodes) {
302
+ for (const s of n.synonyms ?? []) synonyms.set(s.toLowerCase(), n.id);
303
+ }
304
+ const adj = buildAdjacency(nodes);
305
+ const closure = /* @__PURE__ */ new Map();
306
+ for (const n of nodes) closure.set(n.id, closureFrom(n.id, adj));
307
+ return { ids, synonyms, closure };
308
+ }
309
+ var PARENT_UP, PARENT_DOWN, DECAY_FLOOR;
310
+ var init_closure = __esm({
311
+ "../../packages/core/src/vocab/closure.ts"() {
312
+ "use strict";
313
+ PARENT_UP = 0.6;
314
+ PARENT_DOWN = 0.35;
315
+ DECAY_FLOOR = 0.25;
316
+ }
317
+ });
318
+
319
+ // ../../packages/core/src/vocab/types.ts
320
+ var init_types2 = __esm({
321
+ "../../packages/core/src/vocab/types.ts"() {
322
+ "use strict";
323
+ }
324
+ });
325
+
326
+ // ../../packages/core/src/vocab/index.ts
20
327
  function normalize(tokens) {
21
328
  const result = /* @__PURE__ */ new Set();
22
329
  for (const raw of tokens) {
23
330
  const lower = raw.toLowerCase().trim();
24
- if (VOCAB_SET.has(lower)) {
331
+ if (GRAPH.ids.has(lower)) {
25
332
  result.add(lower);
26
333
  continue;
27
334
  }
28
- const mapped = SYNONYMS[lower];
29
- if (mapped && VOCAB_SET.has(mapped)) {
30
- result.add(mapped);
31
- }
335
+ const mapped = GRAPH.synonyms.get(lower);
336
+ if (mapped) result.add(mapped);
32
337
  }
33
338
  return Array.from(result);
34
339
  }
35
- var VOCABULARY, SYNONYMS, VOCAB_SET;
340
+ var GRAPH, VOCABULARY, SYNONYMS;
341
+ var init_vocab = __esm({
342
+ "../../packages/core/src/vocab/index.ts"() {
343
+ "use strict";
344
+ init_graph_data();
345
+ init_closure();
346
+ init_types2();
347
+ init_closure();
348
+ init_graph_data();
349
+ GRAPH = buildGraph(VOCAB_NODES);
350
+ VOCABULARY = [...GRAPH.ids];
351
+ SYNONYMS = Object.fromEntries(GRAPH.synonyms);
352
+ }
353
+ });
354
+
355
+ // ../../packages/core/src/vocabulary.ts
36
356
  var init_vocabulary = __esm({
37
357
  "../../packages/core/src/vocabulary.ts"() {
38
358
  "use strict";
39
- VOCABULARY = [
40
- // Languages
41
- "typescript",
42
- "javascript",
43
- "python",
44
- "go",
45
- "rust",
46
- "java",
47
- "ruby",
48
- "elixir",
49
- "scala",
50
- "kotlin",
51
- "swift",
52
- "cpp",
53
- "csharp",
54
- "php",
55
- "haskell",
56
- "clojure",
57
- "r",
58
- // Frontend frameworks / libs
59
- "react",
60
- "nextjs",
61
- "vue",
62
- "nuxt",
63
- "svelte",
64
- "angular",
65
- "solidjs",
66
- "tailwind",
67
- "css",
68
- "html",
69
- "graphql",
70
- "trpc",
71
- // Backend frameworks
72
- "nodejs",
73
- "express",
74
- "fastify",
75
- "nestjs",
76
- "django",
77
- "fastapi",
78
- "flask",
79
- "rails",
80
- "spring",
81
- "actix",
82
- "gin",
83
- "phoenix",
84
- "laravel",
85
- "dotnet",
86
- // Infrastructure & DevOps
87
- "kubernetes",
88
- "docker",
89
- "terraform",
90
- "aws",
91
- "gcp",
92
- "azure",
93
- "ci-cd",
94
- "github-actions",
95
- "linux",
96
- "nginx",
97
- "pulumi",
98
- "ansible",
99
- "prometheus",
100
- "grafana",
101
- "datadog",
102
- "opentelemetry",
103
- // Data & ML
104
- "postgresql",
105
- "mysql",
106
- "sqlite",
107
- "mongodb",
108
- "redis",
109
- "elasticsearch",
110
- "kafka",
111
- "rabbitmq",
112
- "data-engineering",
113
- "spark",
114
- "airflow",
115
- "dbt",
116
- "ml",
117
- "llm",
118
- "pytorch",
119
- "tensorflow",
120
- "pandas",
121
- "numpy",
122
- // Domains / capabilities
123
- "oauth",
124
- "authentication",
125
- "security",
126
- "payments",
127
- "billing",
128
- "frontend",
129
- "backend",
130
- "devops",
131
- "mobile",
132
- "ios",
133
- "android",
134
- "api-design",
135
- "microservices",
136
- "websockets",
137
- "testing",
138
- "accessibility",
139
- "seo",
140
- "performance",
141
- "observability",
142
- "search",
143
- "realtime"
144
- ];
145
- SYNONYMS = {
146
- // Kubernetes aliases
147
- "k8s": "kubernetes",
148
- "kube": "kubernetes",
149
- // Auth / identity
150
- "passport": "authentication",
151
- "oauth2": "oauth",
152
- "oidc": "oauth",
153
- "jwt": "authentication",
154
- "saml": "authentication",
155
- "auth0": "authentication",
156
- "clerk": "authentication",
157
- "nextauth": "authentication",
158
- // Payments
159
- "@stripe/stripe-js": "payments",
160
- "stripe": "payments",
161
- "braintree": "payments",
162
- "paddle": "payments",
163
- "lemonsqueezy": "payments",
164
- "recurly": "billing",
165
- "chargebee": "billing",
166
- // Framework / lib aliases
167
- "next": "nextjs",
168
- "next.js": "nextjs",
169
- "nuxt.js": "nuxt",
170
- "vue.js": "vue",
171
- "angular.js": "angular",
172
- "angularjs": "angular",
173
- "express.js": "express",
174
- "expressjs": "express",
175
- "fastapi": "fastapi",
176
- "nest": "nestjs",
177
- "nest.js": "nestjs",
178
- "sveltekit": "svelte",
179
- // Language aliases
180
- "ts": "typescript",
181
- "js": "javascript",
182
- "py": "python",
183
- "golang": "go",
184
- "c++": "cpp",
185
- "c#": "csharp",
186
- ".net": "dotnet",
187
- "asp.net": "dotnet",
188
- // DB aliases
189
- "postgres": "postgresql",
190
- "pg": "postgresql",
191
- "mongo": "mongodb",
192
- "elastic": "elasticsearch",
193
- // Cloud aliases
194
- "amazon web services": "aws",
195
- "google cloud": "gcp",
196
- "google cloud platform": "gcp",
197
- "microsoft azure": "azure",
198
- // CI/CD aliases
199
- "github actions": "github-actions",
200
- "circle ci": "ci-cd",
201
- "circleci": "ci-cd",
202
- "jenkins": "ci-cd",
203
- "gitlab ci": "ci-cd",
204
- "travis": "ci-cd",
205
- // Mobile
206
- "react native": "mobile",
207
- "flutter": "mobile",
208
- "expo": "mobile",
209
- // AI / ML
210
- "openai": "llm",
211
- "anthropic": "llm",
212
- "langchain": "llm",
213
- "llamaindex": "llm",
214
- "hugging face": "ml",
215
- "huggingface": "ml",
216
- "scikit-learn": "ml",
217
- "sklearn": "ml",
218
- // Data pipeline
219
- "apache kafka": "kafka",
220
- "apache spark": "spark",
221
- "apache airflow": "airflow",
222
- // Misc
223
- "tailwindcss": "tailwind",
224
- "tw": "tailwind",
225
- "gql": "graphql",
226
- "ws": "websockets",
227
- "socket.io": "websockets",
228
- "jest": "testing",
229
- "vitest": "testing",
230
- "playwright": "testing",
231
- "cypress": "testing"
232
- };
233
- VOCAB_SET = new Set(VOCABULARY);
359
+ init_vocab();
234
360
  }
235
361
  });
236
362
 
@@ -238,6 +364,7 @@ var init_vocabulary = __esm({
238
364
  var init_matcher = __esm({
239
365
  "../../packages/core/src/matcher.ts"() {
240
366
  "use strict";
367
+ init_vocabulary();
241
368
  }
242
369
  });
243
370
 
@@ -273,11 +400,19 @@ var init_himalayas = __esm({
273
400
  }
274
401
  });
275
402
 
403
+ // ../../packages/core/src/feeds/entities.ts
404
+ var init_entities = __esm({
405
+ "../../packages/core/src/feeds/entities.ts"() {
406
+ "use strict";
407
+ }
408
+ });
409
+
276
410
  // ../../packages/core/src/feeds/wwr.ts
277
411
  var init_wwr = __esm({
278
412
  "../../packages/core/src/feeds/wwr.ts"() {
279
413
  "use strict";
280
414
  init_vocabulary();
415
+ init_entities();
281
416
  }
282
417
  });
283
418
 
@@ -286,6 +421,24 @@ var init_hn = __esm({
286
421
  "../../packages/core/src/feeds/hn.ts"() {
287
422
  "use strict";
288
423
  init_vocabulary();
424
+ init_entities();
425
+ }
426
+ });
427
+
428
+ // ../../packages/core/src/feeds/bounty-gate.ts
429
+ var init_bounty_gate = __esm({
430
+ "../../packages/core/src/feeds/bounty-gate.ts"() {
431
+ "use strict";
432
+ }
433
+ });
434
+
435
+ // ../../packages/core/src/feeds/github-bounties.ts
436
+ var init_github_bounties = __esm({
437
+ "../../packages/core/src/feeds/github-bounties.ts"() {
438
+ "use strict";
439
+ init_vocabulary();
440
+ init_entities();
441
+ init_bounty_gate();
289
442
  }
290
443
  });
291
444
 
@@ -303,6 +456,8 @@ var init_feeds = __esm({
303
456
  init_himalayas();
304
457
  init_wwr();
305
458
  init_hn();
459
+ init_github_bounties();
460
+ init_bounty_gate();
306
461
  GREENHOUSE_SLUGS_BY_TIER = {
307
462
  bigco: [
308
463
  "stripe",
@@ -411,13 +566,22 @@ var init_feeds = __esm({
411
566
  }
412
567
  });
413
568
 
414
- // ../../packages/core/src/coastal.ts
569
+ // ../../packages/core/src/partners.ts
415
570
  import { readFileSync } from "fs";
416
571
  import { join } from "path";
417
572
  import { fileURLToPath } from "url";
418
- var init_coastal = __esm({
419
- "../../packages/core/src/coastal.ts"() {
573
+ var EXAMPLE_BUYER, BUYER_REGISTRY;
574
+ var init_partners = __esm({
575
+ "../../packages/core/src/partners.ts"() {
420
576
  "use strict";
577
+ EXAMPLE_BUYER = {
578
+ id: "northstar",
579
+ legalName: "Northstar Talent Partners",
580
+ matchCriteria: { roleTypes: ["full_time"] }
581
+ };
582
+ BUYER_REGISTRY = {
583
+ [EXAMPLE_BUYER.id]: EXAMPLE_BUYER
584
+ };
421
585
  }
422
586
  });
423
587
 
@@ -426,7 +590,7 @@ var init_indexer = __esm({
426
590
  "../../packages/core/src/indexer.ts"() {
427
591
  "use strict";
428
592
  init_feeds();
429
- init_coastal();
593
+ init_partners();
430
594
  }
431
595
  });
432
596
 
@@ -447,7 +611,7 @@ var init_src = __esm({
447
611
  init_matcher();
448
612
  init_feeds();
449
613
  init_indexer();
450
- init_coastal();
614
+ init_partners();
451
615
  init_github();
452
616
  }
453
617
  });
@@ -546,10 +710,10 @@ function migrateTagWeights(profile) {
546
710
  if (!profile.tagWeights) {
547
711
  profile.tagWeights = {};
548
712
  }
549
- const now = (/* @__PURE__ */ new Date()).toISOString();
713
+ const seed = profile.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString();
550
714
  for (const tag of profile.skillTags) {
551
715
  if (!profile.tagWeights[tag]) {
552
- profile.tagWeights[tag] = { count: 1, firstSeen: now, lastSeen: now, sessions: 1 };
716
+ profile.tagWeights[tag] = { count: 1, firstSeen: seed, lastSeen: seed, sessions: 1 };
553
717
  }
554
718
  }
555
719
  }
@@ -575,7 +739,7 @@ async function writeProfile(profile) {
575
739
  const blob = encrypt(JSON.stringify(profile), key);
576
740
  writeFileSync(PROFILE_FILE, JSON.stringify(blob, null, 2), { encoding: "utf8" });
577
741
  }
578
- function accumulateSession(profile, tags, isEmployerContext, inferredSeniority) {
742
+ function accumulateSession(profile, tags, isEmployerContext, inferredSeniority, seniorityIsAuthoritative = false) {
579
743
  const now = (/* @__PURE__ */ new Date()).toISOString();
580
744
  let filtered = normalize(tags);
581
745
  if (isEmployerContext) {
@@ -593,7 +757,9 @@ function accumulateSession(profile, tags, isEmployerContext, inferredSeniority)
593
757
  }
594
758
  }
595
759
  if (inferredSeniority && !isEmployerContext) {
596
- profile.seniority = inferredSeniority;
760
+ if (seniorityIsAuthoritative || !profile.github) {
761
+ profile.seniority = inferredSeniority;
762
+ }
597
763
  }
598
764
  }
599
765
  async function accumulateTags(rawTokens, isEmployerContext, inferredSeniority) {
@@ -601,12 +767,14 @@ async function accumulateTags(rawTokens, isEmployerContext, inferredSeniority) {
601
767
  accumulateSession(profile, rawTokens, isEmployerContext, inferredSeniority);
602
768
  await writeProfile(profile);
603
769
  }
604
- function accumulateGitHubTags(profile, tags) {
770
+ function accumulateGitHubTags(profile, tags, inferredSeniority) {
605
771
  accumulateSession(
606
772
  profile,
607
773
  tags,
608
774
  /* isEmployerContext */
609
- false
775
+ false,
776
+ inferredSeniority,
777
+ true
610
778
  );
611
779
  }
612
780
  async function listSavedJobs() {