job-forge 2.0.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.
Files changed (79) hide show
  1. package/.codex/config.toml +8 -0
  2. package/.cursor/mcp.json +21 -0
  3. package/.cursor/rules/main.mdc +519 -0
  4. package/.mcp.json +21 -0
  5. package/.opencode/agents/general-free.md +85 -0
  6. package/.opencode/agents/general-paid.md +39 -0
  7. package/.opencode/agents/glm-minimal.md +50 -0
  8. package/.opencode/skills/job-forge.md +185 -0
  9. package/AGENTS.md +514 -0
  10. package/CLAUDE.md +514 -0
  11. package/LICENSE +21 -0
  12. package/README.md +195 -0
  13. package/batch/README.md +60 -0
  14. package/batch/batch-prompt.md +399 -0
  15. package/batch/batch-runner.sh +673 -0
  16. package/bin/create-job-forge.mjs +375 -0
  17. package/bin/job-forge.mjs +120 -0
  18. package/bin/sync.mjs +141 -0
  19. package/config/profile.example.yml +67 -0
  20. package/cv-sync-check.mjs +128 -0
  21. package/dedup-tracker.mjs +201 -0
  22. package/docs/ARCHITECTURE.md +220 -0
  23. package/docs/CUSTOMIZATION.md +101 -0
  24. package/docs/MODEL-ROUTING.md +195 -0
  25. package/docs/README.md +54 -0
  26. package/docs/SETUP.md +186 -0
  27. package/docs/demo.gif +0 -0
  28. package/fonts/dm-sans-latin-ext.woff2 +0 -0
  29. package/fonts/dm-sans-latin.woff2 +0 -0
  30. package/fonts/space-grotesk-latin-ext.woff2 +0 -0
  31. package/fonts/space-grotesk-latin.woff2 +0 -0
  32. package/generate-pdf.mjs +168 -0
  33. package/iso/agents/general-free.md +90 -0
  34. package/iso/agents/general-paid.md +44 -0
  35. package/iso/agents/glm-minimal.md +55 -0
  36. package/iso/commands/job-forge.md +188 -0
  37. package/iso/config.json +7 -0
  38. package/iso/instructions.md +514 -0
  39. package/iso/mcp.json +15 -0
  40. package/merge-tracker.mjs +377 -0
  41. package/modes/README.md +30 -0
  42. package/modes/_shared-calibration.md +26 -0
  43. package/modes/_shared.md +272 -0
  44. package/modes/apply.md +257 -0
  45. package/modes/auto-pipeline.md +70 -0
  46. package/modes/batch.md +110 -0
  47. package/modes/compare.md +23 -0
  48. package/modes/contact.md +82 -0
  49. package/modes/deep.md +99 -0
  50. package/modes/followup.md +68 -0
  51. package/modes/negotiation.md +146 -0
  52. package/modes/offer.md +199 -0
  53. package/modes/pdf.md +121 -0
  54. package/modes/pipeline.md +83 -0
  55. package/modes/project.md +30 -0
  56. package/modes/rejection.md +92 -0
  57. package/modes/scan.md +185 -0
  58. package/modes/tracker.md +31 -0
  59. package/modes/training.md +27 -0
  60. package/normalize-statuses.mjs +152 -0
  61. package/opencode.json +28 -0
  62. package/package.json +78 -0
  63. package/scripts/add-tags.mjs +894 -0
  64. package/scripts/cursor-agent-loop.sh +211 -0
  65. package/scripts/cursor-agent-stream-format.py +134 -0
  66. package/scripts/next-num.mjs +33 -0
  67. package/scripts/release/check-source.mjs +37 -0
  68. package/scripts/render-report-header.mjs +78 -0
  69. package/scripts/session-report.mjs +129 -0
  70. package/scripts/slugify.mjs +27 -0
  71. package/scripts/today.mjs +20 -0
  72. package/scripts/token-usage-report.mjs +315 -0
  73. package/scripts/tracker-line.mjs +67 -0
  74. package/scripts/verify-greenhouse-urls.mjs +195 -0
  75. package/templates/cv-template.html +395 -0
  76. package/templates/portals.example.yml +3140 -0
  77. package/templates/states.yml +62 -0
  78. package/tracker-lib.mjs +257 -0
  79. package/verify-pipeline.mjs +267 -0
@@ -0,0 +1,894 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * add-tags.mjs
5
+ *
6
+ * Reads templates/portals.example.yml line-by-line and inserts a `tags:` array
7
+ * on the line before `enabled:` for each tracked company. Preserves all
8
+ * comments, blank lines, and formatting exactly.
9
+ *
10
+ * Tag taxonomy is defined inline; assignment is driven by:
11
+ * 1. The most-recent section comment (e.g. "# -- AI Labs & LLM providers --")
12
+ * 2. The company name
13
+ * 3. The `notes:` field (location, product signals, etc.)
14
+ */
15
+
16
+ import { readFileSync, writeFileSync } from "node:fs";
17
+ import { resolve, dirname } from "node:path";
18
+ import { fileURLToPath } from "node:url";
19
+
20
+ const __dirname = dirname(fileURLToPath(import.meta.url));
21
+ const FILE = resolve(__dirname, "..", "templates", "portals.example.yml");
22
+
23
+ // ── helpers ──────────────────────────────────────────────────────────────
24
+
25
+ /** Case-insensitive check for any of `needles` inside `haystack`. */
26
+ const has = (haystack, ...needles) =>
27
+ needles.some((n) => haystack.toLowerCase().includes(n.toLowerCase()));
28
+
29
+ // ── per-company tag logic ────────────────────────────────────────────────
30
+
31
+ /**
32
+ * Return 2-5 tags for a company given its context.
33
+ *
34
+ * @param {string} section Most recent "# -- … --" header
35
+ * @param {string} name Company name
36
+ * @param {string} notes notes: field value (may be "")
37
+ * @returns {string[]}
38
+ */
39
+ function assignTags(section, name, notes) {
40
+ const tags = new Set();
41
+ const ctx = `${section} ${name} ${notes}`.toLowerCase();
42
+
43
+ // ── Section-based primary tags ──
44
+
45
+ if (has(section, "AI Labs", "LLM provider", "Model Provider")) {
46
+ tags.add("ai-lab");
47
+ }
48
+ if (has(section, "Voice AI", "Conversational AI")) {
49
+ tags.add("voice-ai");
50
+ tags.add("conversational-ai");
51
+ }
52
+ if (has(section, "Contact Center", "Enterprise comms", "contact center")) {
53
+ tags.add("conversational-ai");
54
+ }
55
+ if (has(section, "AI infra", "LLMOps", "AI Infrastructure", "Compute")) {
56
+ tags.add("ai-infra");
57
+ }
58
+ if (has(section, "No-Code", "Low-Code", "Automation")) {
59
+ tags.add("automation");
60
+ }
61
+ if (has(section, "AI-native platform", "FDE/SA")) {
62
+ tags.add("developer-tools");
63
+ }
64
+ if (has(section, "Vector DB", "RAG Infrastructure")) {
65
+ tags.add("vector-db");
66
+ }
67
+ if (has(section, "AI-Native Developer Tool", "AI Coding", "Code Gen")) {
68
+ tags.add("ai-coding");
69
+ tags.add("developer-tools");
70
+ }
71
+ if (has(section, "Data & ML Platform")) {
72
+ tags.add("analytics");
73
+ tags.add("developer-tools");
74
+ }
75
+ if (has(section, "Developer Platform", "AI-adjacent")) {
76
+ tags.add("developer-tools");
77
+ }
78
+ if (has(section, "Security", "Cybersecurity")) {
79
+ tags.add("security");
80
+ }
81
+ if (has(section, "Fintech")) {
82
+ tags.add("fintech");
83
+ }
84
+ if (has(section, "Design", "Collaboration")) {
85
+ tags.add("collaboration");
86
+ }
87
+ if (has(section, "HR", "Remote Work")) {
88
+ tags.add("hr-tech");
89
+ }
90
+ if (has(section, "Big Tech", "Major Cloud")) {
91
+ tags.add("ai-lab");
92
+ tags.add("cloud");
93
+ }
94
+ if (has(section, "Autonomous", "Robotics")) {
95
+ tags.add("autonomous");
96
+ tags.add("robotics");
97
+ }
98
+ if (has(section, "Healthcare")) {
99
+ tags.add("healthcare");
100
+ }
101
+ if (has(section, "Legal", "Compliance AI")) {
102
+ tags.add("legal-tech");
103
+ }
104
+ if (has(section, "Enterprise SaaS", "Productivity")) {
105
+ tags.add("enterprise-saas");
106
+ tags.add("productivity");
107
+ }
108
+ if (has(section, "E-commerce", "Marketplace")) {
109
+ tags.add("e-commerce");
110
+ }
111
+ if (has(section, "DevOps", "CI/CD", "Infrastructure")) {
112
+ tags.add("devops");
113
+ }
114
+ if (has(section, "Data Analytics", "BI")) {
115
+ tags.add("analytics");
116
+ }
117
+ if (has(section, "Sales", "Marketing", "RevOps")) {
118
+ tags.add("crm");
119
+ tags.add("automation");
120
+ }
121
+ if (has(section, "AI Agent", "Workflow Automation")) {
122
+ tags.add("ai-agents");
123
+ tags.add("automation");
124
+ }
125
+ if (has(section, "Cloud-Native", "Kubernetes")) {
126
+ tags.add("cloud");
127
+ tags.add("devops");
128
+ }
129
+ if (has(section, "EdTech", "Learning")) {
130
+ tags.add("edtech");
131
+ }
132
+ if (has(section, "Gaming", "Creative AI")) {
133
+ tags.add("gaming");
134
+ }
135
+ if (has(section, "Climate", "Energy")) {
136
+ tags.add("climate");
137
+ }
138
+ if (has(section, "Supply Chain", "Logistics")) {
139
+ tags.add("logistics");
140
+ }
141
+ if (has(section, "Real Estate", "PropTech")) {
142
+ tags.add("real-estate");
143
+ }
144
+ if (has(section, "Telecom", "Connectivity")) {
145
+ tags.add("networking");
146
+ }
147
+ if (has(section, "Music", "Audio AI")) {
148
+ tags.add("media");
149
+ }
150
+ if (has(section, "Travel", "Mobility")) {
151
+ tags.add("travel");
152
+ }
153
+ if (has(section, "Insurance", "RegTech")) {
154
+ tags.add("insurance");
155
+ }
156
+ if (has(section, "Communication Platform")) {
157
+ tags.add("communication");
158
+ }
159
+ if (has(section, "Observability", "Monitoring")) {
160
+ tags.add("observability");
161
+ }
162
+ if (has(section, "Database", "Data Infrastructure")) {
163
+ tags.add("database");
164
+ }
165
+ if (has(section, "AI Search", "Knowledge")) {
166
+ tags.add("ai-search");
167
+ }
168
+ if (has(section, "Developer Experience", "API")) {
169
+ tags.add("developer-tools");
170
+ }
171
+ if (has(section, "European tech", "EMEA")) {
172
+ tags.add("eu");
173
+ }
174
+ if (has(section, "Israel Tech")) {
175
+ tags.add("israel");
176
+ }
177
+ if (has(section, "India Tech")) {
178
+ tags.add("apac");
179
+ }
180
+ if (has(section, "Horizontal AI Platform")) {
181
+ tags.add("mlops");
182
+ }
183
+ if (has(section, "Vertical AI")) {
184
+ tags.add("enterprise-saas");
185
+ }
186
+ if (has(section, "Identity", "Trust")) {
187
+ tags.add("identity");
188
+ }
189
+ if (has(section, "Networking", "Edge")) {
190
+ tags.add("networking");
191
+ }
192
+ if (has(section, "Testing", "QA")) {
193
+ tags.add("testing");
194
+ }
195
+ if (has(section, "Open Source Companies")) {
196
+ tags.add("open-source");
197
+ tags.add("developer-tools");
198
+ }
199
+ if (has(section, "Media", "Content")) {
200
+ tags.add("media");
201
+ }
202
+ if (has(section, "Food", "AgTech")) {
203
+ tags.add("food-tech");
204
+ }
205
+ if (has(section, "Construction", "Industrial")) {
206
+ tags.add("construction");
207
+ }
208
+ if (has(section, "Government", "Civic")) {
209
+ tags.add("govtech");
210
+ tags.add("defense");
211
+ }
212
+ if (has(section, "Misc High-Growth")) {
213
+ tags.add("developer-tools");
214
+ }
215
+ if (has(section, "Ashby-based", "Lever-based", "Greenhouse-based")) {
216
+ // These are grouping headers by ATS, not industry -- rely on name/notes
217
+ }
218
+
219
+ // ── Name / notes refinements ──
220
+
221
+ // AI signals from notes/name
222
+ if (has(ctx, "llmops")) tags.add("llmops");
223
+ if (has(ctx, "mlops") || has(ctx, "experiment tracking") || has(ctx, "ml metadata")) tags.add("mlops");
224
+ if (has(ctx, "observability") && !tags.has("observability")) tags.add("observability");
225
+ if (has(ctx, "vector") || has(ctx, "embeddings database")) tags.add("vector-db");
226
+ if (has(ctx, "voice ai") || has(ctx, "tts") || has(ctx, "stt") || has(ctx, "speech")) tags.add("voice-ai");
227
+ if (has(ctx, "gpu cloud") || has(ctx, "gpu marketplace") || has(ctx, "gpu droplet")) tags.add("gpu-cloud");
228
+ if (has(ctx, "inference") && has(ctx, "hardware") || has(ctx, "wafer-scale") || has(ctx, "ai chip") || has(ctx, "ai accelerator") || has(ctx, "lpu")) tags.add("chips");
229
+ if (has(ctx, "no-code") || has(ctx, "no code")) tags.add("no-code");
230
+ if (has(ctx, "low-code") || has(ctx, "low code")) tags.add("low-code");
231
+ if (has(ctx, "rpa")) tags.add("rpa");
232
+ if (has(ctx, "open-source") || has(ctx, "open source")) tags.add("open-source");
233
+ if (has(ctx, "ai agent") || has(ctx, "ai agents") || has(ctx, "autonomous coding") || has(ctx, "ai software engineer")) tags.add("ai-agents");
234
+ if (has(ctx, "ai search") || has(ctx, "search and answer")) tags.add("ai-search");
235
+ if (has(ctx, "creative") || has(ctx, "image generation") || has(ctx, "video generation") || has(ctx, "3d capture")) tags.add("ai-creative");
236
+ if (has(ctx, "generative ai") || has(ctx, "genai") || has(ctx, "generative model")) tags.add("ai-lab");
237
+ if (has(ctx, "contact center") || has(ctx, "customer service") || has(ctx, "customer support")) tags.add("conversational-ai");
238
+ if (has(ctx, "payments") || has(ctx, "payment") || has(ctx, "banking") || has(ctx, "bnpl") || has(ctx, "neobank") || has(ctx, "money transfer") || has(ctx, "trading platform") || has(ctx, "corporate finance") || has(ctx, "corporate card") || has(ctx, "financial")) tags.add("fintech");
239
+ if (has(ctx, "defense") || has(ctx, "military") || has(ctx, "intelligence")) tags.add("defense");
240
+ if (has(ctx, "robotics") || has(ctx, "humanoid") || has(ctx, "robotic")) tags.add("robotics");
241
+ if (has(ctx, "autonomous driv") || has(ctx, "self-driving") || has(ctx, "autonomous vehicle") || has(ctx, "autonomous delivery")) tags.add("autonomous");
242
+ if (has(ctx, "database") || has(ctx, "postgres") || has(ctx, "mysql") || has(ctx, "sql") || has(ctx, "olap")) tags.add("database");
243
+ if (has(ctx, "healthcare") || has(ctx, "health") || has(ctx, "medical") || has(ctx, "precision medicine") || has(ctx, "pathology") || has(ctx, "drug discovery") || has(ctx, "oncology") || has(ctx, "life sciences")) tags.add("healthcare");
244
+ if (has(ctx, "legal") || has(ctx, "contract management") || has(ctx, "e-signature")) tags.add("legal-tech");
245
+ if (has(ctx, "construction") || has(ctx, "construction management")) tags.add("construction");
246
+ if (has(ctx, "fraud") && has(ctx, "financial")) tags.add("fintech");
247
+ if (has(ctx, "process mining")) tags.add("automation");
248
+ if (has(ctx, "compliance") || has(ctx, "soc 2") || has(ctx, "supply chain security")) tags.add("compliance");
249
+ if (has(ctx, "identity verification") || has(ctx, "ekyc") || has(ctx, "auth") || has(ctx, "sso") || has(ctx, "access management")) tags.add("identity");
250
+ if (has(ctx, "incident management") || has(ctx, "aiops")) tags.add("observability");
251
+ if (has(ctx, "feature flag")) tags.add("developer-tools");
252
+ if (has(ctx, "ai coding") || has(ctx, "code completion") || has(ctx, "code assistant") || has(ctx, "ai-native editor") || has(ctx, "coding agent") || has(ctx, "code generation") || has(ctx, "ai writing")) tags.add("ai-coding");
253
+ if (has(ctx, "cms") || has(ctx, "content platform") || has(ctx, "headless cms")) tags.add("developer-tools");
254
+
255
+ // ── Company-specific overrides for big tech and notable names ──
256
+
257
+ const n = name.toLowerCase();
258
+
259
+ // Big tech
260
+ if (n === "anthropic") { tags.add("ai-lab"); tags.add("us"); }
261
+ if (n === "openai") { tags.add("ai-lab"); tags.add("us"); }
262
+ if (n === "meta") { tags.add("ai-lab"); tags.add("us"); }
263
+ if (n === "microsoft") { tags.add("ai-lab"); tags.add("cloud"); tags.add("us"); }
264
+ if (n === "nvidia") { tags.add("ai-lab"); tags.add("chips"); tags.add("gpu-cloud"); tags.add("us"); }
265
+ if (n === "google") { tags.add("ai-lab"); tags.add("cloud"); tags.add("us"); }
266
+ if (n === "google deepmind") { tags.add("ai-lab"); tags.add("uk"); tags.add("us"); }
267
+ if (n.includes("amazon")) { tags.add("ai-lab"); tags.add("cloud"); tags.add("us"); }
268
+ if (n === "apple") { tags.add("ai-lab"); tags.add("us"); }
269
+ if (n === "ibm") { tags.add("ai-lab"); tags.add("cloud"); tags.add("us"); }
270
+ if (n === "intel") { tags.add("chips"); tags.add("us"); }
271
+ if (n === "amd") { tags.add("chips"); tags.add("gpu-cloud"); tags.add("us"); }
272
+ if (n === "qualcomm") { tags.add("chips"); tags.add("us"); }
273
+ if (n === "oracle") { tags.add("cloud"); tags.add("enterprise-saas"); tags.add("us"); }
274
+ if (n === "sap ai") { tags.add("enterprise-saas"); tags.add("eu"); }
275
+ if (n === "cisco") { tags.add("networking"); tags.add("us"); }
276
+ if (n === "dell technologies") { tags.add("cloud"); tags.add("us"); }
277
+ if (n === "hpe") { tags.add("cloud"); tags.add("us"); }
278
+
279
+ // AI labs & model providers
280
+ if (n === "xai") { tags.add("ai-lab"); tags.add("us"); }
281
+ if (n === "scale") { tags.add("ai-lab"); tags.add("ai-infra"); tags.add("us"); }
282
+ if (n === "databricks") { tags.add("ai-infra"); tags.add("analytics"); tags.add("us"); }
283
+ if (n === "snowflake") { tags.add("cloud"); tags.add("analytics"); tags.add("us"); }
284
+ if (n === "confluent") { tags.add("developer-tools"); tags.add("us"); }
285
+ if (n === "perplexity") { tags.add("ai-lab"); tags.add("ai-search"); tags.add("us"); }
286
+ if (n === "replicate") { tags.add("ai-infra"); tags.add("us"); }
287
+ if (n === "hugging face") { tags.add("ai-lab"); tags.add("open-source"); tags.add("us"); }
288
+ if (n === "groq") { tags.add("ai-infra"); tags.add("chips"); tags.add("us"); }
289
+ if (n === "coreweave") { tags.add("ai-infra"); tags.add("gpu-cloud"); tags.add("us"); }
290
+ if (n === "lambda") { tags.add("ai-infra"); tags.add("gpu-cloud"); tags.add("us"); }
291
+ if (n === "modal") { tags.add("ai-infra"); tags.add("gpu-cloud"); tags.add("us"); }
292
+ if (n === "fireworks ai") { tags.add("ai-infra"); tags.add("us"); }
293
+ if (n === "together ai") { tags.add("ai-infra"); tags.add("open-source"); tags.add("us"); }
294
+ if (n === "anyscale") { tags.add("ai-infra"); tags.add("us"); }
295
+ if (n === "mistral ai") { tags.add("ai-lab"); tags.add("eu"); }
296
+ if (n === "stability ai") { tags.add("ai-lab"); tags.add("ai-creative"); tags.add("uk"); }
297
+ if (n === "ai21 labs") { tags.add("ai-lab"); tags.add("israel"); }
298
+ if (n === "character ai") { tags.add("ai-lab"); tags.add("conversational-ai"); tags.add("us"); }
299
+ if (n === "reka ai") { tags.add("ai-lab"); tags.add("us"); }
300
+ if (n === "aleph alpha") { tags.add("ai-lab"); tags.add("eu"); }
301
+ if (n === "cohere") { tags.add("ai-lab"); tags.add("remote-first"); }
302
+ if (n === "cerebras") { tags.add("ai-infra"); tags.add("chips"); tags.add("us"); }
303
+ if (n === "sambanova") { tags.add("ai-infra"); tags.add("chips"); tags.add("us"); }
304
+ if (n === "modular") { tags.add("ai-infra"); tags.add("developer-tools"); tags.add("us"); }
305
+ if (n === "baseten") { tags.add("ai-infra"); tags.add("us"); }
306
+ if (n === "runpod") { tags.add("ai-infra"); tags.add("gpu-cloud"); tags.add("us"); }
307
+ if (n === "vast.ai") { tags.add("ai-infra"); tags.add("gpu-cloud"); tags.add("us"); }
308
+
309
+ // Voice AI
310
+ if (n === "polyai") { tags.add("voice-ai"); tags.add("uk"); }
311
+ if (n === "parloa") { tags.add("voice-ai"); tags.add("eu"); }
312
+ if (n === "hume ai") { tags.add("voice-ai"); tags.add("us"); }
313
+ if (n === "elevenlabs") { tags.add("voice-ai"); tags.add("us"); }
314
+ if (n === "deepgram") { tags.add("voice-ai"); tags.add("us"); }
315
+ if (n === "vapi") { tags.add("voice-ai"); tags.add("ai-infra"); tags.add("us"); }
316
+ if (n === "bland ai") { tags.add("voice-ai"); tags.add("ai-agents"); tags.add("us"); }
317
+ if (n === "soundhound") { tags.add("voice-ai"); tags.add("us"); }
318
+ if (n === "assemblyai") { tags.add("voice-ai"); tags.add("us"); }
319
+ if (n === "speechmatics") { tags.add("voice-ai"); tags.add("uk"); }
320
+
321
+ // Contact center / CX
322
+ if (n === "intercom") { tags.add("conversational-ai"); tags.add("enterprise-saas"); tags.add("eu"); }
323
+ if (n === "ada") { tags.add("conversational-ai"); tags.add("ai-agents"); tags.add("remote-first"); }
324
+ if (n === "liveperson") { tags.add("conversational-ai"); tags.add("remote-first"); }
325
+ if (n === "sierra") { tags.add("conversational-ai"); tags.add("ai-agents"); tags.add("us"); }
326
+ if (n === "decagon") { tags.add("conversational-ai"); tags.add("ai-agents"); tags.add("us"); }
327
+ if (n === "talkdesk") { tags.add("conversational-ai"); tags.add("eu"); }
328
+ if (n === "twilio") { tags.add("communication"); tags.add("us"); }
329
+ if (n === "dialpad") { tags.add("voice-ai"); tags.add("communication"); tags.add("us"); }
330
+ if (n === "gong") { tags.add("voice-ai"); tags.add("crm"); tags.add("us"); }
331
+ if (n === "genesys") { tags.add("conversational-ai"); tags.add("us"); }
332
+ if (n === "salesforce") { tags.add("crm"); tags.add("ai-agents"); tags.add("us"); }
333
+ if (n === "cognigy") { tags.add("conversational-ai"); tags.add("eu"); }
334
+
335
+ // AI infra & LLMOps
336
+ if (n === "langfuse") { tags.add("llmops"); tags.add("eu"); }
337
+ if (n === "lindy") { tags.add("ai-agents"); tags.add("us"); }
338
+ if (n === "langchain") { tags.add("ai-infra"); tags.add("developer-tools"); tags.add("us"); }
339
+ if (n === "arize ai") { tags.add("llmops"); tags.add("observability"); tags.add("us"); }
340
+
341
+ // Vector DBs
342
+ if (n === "pinecone") { tags.add("vector-db"); tags.add("us"); }
343
+ if (n === "weaviate") { tags.add("vector-db"); tags.add("open-source"); tags.add("eu"); }
344
+ if (n === "qdrant") { tags.add("vector-db"); tags.add("open-source"); tags.add("eu"); }
345
+ if (n === "chroma") { tags.add("vector-db"); tags.add("open-source"); tags.add("us"); }
346
+ if (n === "zilliz") { tags.add("vector-db"); tags.add("us"); }
347
+ if (n === "vectara") { tags.add("vector-db"); tags.add("ai-search"); tags.add("us"); }
348
+ if (n === "unstructured") { tags.add("ai-infra"); tags.add("us"); }
349
+
350
+ // AI coding
351
+ if (n === "cursor") { tags.add("ai-coding"); tags.add("developer-tools"); tags.add("us"); }
352
+ if (n === "replit") { tags.add("ai-coding"); tags.add("developer-tools"); tags.add("us"); }
353
+ if (n === "sourcegraph") { tags.add("ai-coding"); tags.add("developer-tools"); tags.add("us"); }
354
+ if (n === "codeium") { tags.add("ai-coding"); tags.add("developer-tools"); tags.add("us"); }
355
+ if (n === "tabnine") { tags.add("ai-coding"); tags.add("developer-tools"); tags.add("israel"); }
356
+ if (n === "augment code") { tags.add("ai-coding"); tags.add("us"); }
357
+ if (n === "magic ai") { tags.add("ai-coding"); tags.add("ai-lab"); tags.add("us"); }
358
+ if (n === "poolside") { tags.add("ai-coding"); tags.add("ai-lab"); tags.add("us"); }
359
+ if (n.includes("cognition")) { tags.add("ai-coding"); tags.add("ai-agents"); tags.add("us"); }
360
+ if (n === "factory ai") { tags.add("ai-coding"); tags.add("ai-agents"); tags.add("us"); }
361
+
362
+ // Developer platforms
363
+ if (n === "retool") { tags.add("developer-tools"); tags.add("no-code"); tags.add("uk"); }
364
+ if (n === "airtable") { tags.add("no-code"); tags.add("productivity"); tags.add("us"); }
365
+ if (n === "vercel") { tags.add("developer-tools"); tags.add("us"); }
366
+ if (n === "cloudflare") { tags.add("cloud"); tags.add("networking"); tags.add("us"); }
367
+ if (n === "gitlab") { tags.add("devops"); tags.add("developer-tools"); tags.add("remote-first"); }
368
+ if (n === "linear") { tags.add("developer-tools"); tags.add("productivity"); tags.add("us"); }
369
+ if (n === "notion") { tags.add("productivity"); tags.add("us"); }
370
+ if (n === "temporal") { tags.add("developer-tools"); tags.add("us"); }
371
+ if (n === "writer") { tags.add("ai-creative"); tags.add("enterprise-saas"); tags.add("us"); }
372
+
373
+ // No-code / Automation
374
+ if (n === "n8n") { tags.add("automation"); tags.add("no-code"); tags.add("open-source"); tags.add("eu"); }
375
+ if (n === "zapier") { tags.add("automation"); tags.add("no-code"); tags.add("remote-first"); }
376
+ if (n.includes("make.com")) { tags.add("automation"); tags.add("no-code"); tags.add("eu"); }
377
+
378
+ // Databases
379
+ if (n === "mongodb") { tags.add("database"); tags.add("us"); }
380
+ if (n === "supabase") { tags.add("database"); tags.add("developer-tools"); tags.add("remote-first"); }
381
+ if (n === "neon") { tags.add("database"); tags.add("developer-tools"); tags.add("us"); }
382
+ if (n === "planetscale") { tags.add("database"); tags.add("developer-tools"); tags.add("us"); }
383
+ if (n === "cockroachdb") { tags.add("database"); tags.add("us"); }
384
+ if (n === "singlestore") { tags.add("database"); tags.add("analytics"); tags.add("us"); }
385
+ if (n === "clickhouse") { tags.add("database"); tags.add("analytics"); tags.add("us"); }
386
+ if (n === "timescaledb") { tags.add("database"); tags.add("us"); }
387
+ if (n === "starrocks") { tags.add("database"); tags.add("analytics"); tags.add("us"); }
388
+ if (n === "motherduck") { tags.add("database"); tags.add("analytics"); tags.add("us"); }
389
+ if (n === "turso") { tags.add("database"); tags.add("developer-tools"); tags.add("us"); }
390
+ if (n === "materialize") { tags.add("database"); tags.add("us"); }
391
+ if (n === "risingwave") { tags.add("database"); tags.add("us"); }
392
+
393
+ // Observability
394
+ if (n === "elastic") { tags.add("observability"); tags.add("ai-search"); tags.add("us"); }
395
+ if (n === "datadog") { tags.add("observability"); tags.add("us"); }
396
+ if (n === "grafana labs") { tags.add("observability"); tags.add("open-source"); tags.add("remote-first"); }
397
+ if (n === "new relic") { tags.add("observability"); tags.add("us"); }
398
+ if (n.includes("splunk")) { tags.add("observability"); tags.add("security"); tags.add("us"); }
399
+ if (n === "chronosphere") { tags.add("observability"); tags.add("us"); }
400
+ if (n === "honeycomb") { tags.add("observability"); tags.add("us"); }
401
+ if (n === "sentry") { tags.add("observability"); tags.add("developer-tools"); tags.add("us"); }
402
+
403
+ // Security
404
+ if (n === "wiz") { tags.add("security"); tags.add("cloud"); tags.add("us"); }
405
+ if (n === "snyk") { tags.add("security"); tags.add("developer-tools"); tags.add("us"); }
406
+ if (n === "crowdstrike") { tags.add("security"); tags.add("us"); }
407
+ if (n === "palo alto networks") { tags.add("security"); tags.add("us"); }
408
+ if (n === "fortinet") { tags.add("security"); tags.add("us"); }
409
+ if (n === "zscaler") { tags.add("security"); tags.add("cloud"); tags.add("us"); }
410
+ if (n === "sentinelone") { tags.add("security"); tags.add("us"); }
411
+ if (n === "lacework") { tags.add("security"); tags.add("cloud"); tags.add("us"); }
412
+ if (n === "okta") { tags.add("identity"); tags.add("security"); tags.add("us"); }
413
+ if (n === "1password") { tags.add("security"); tags.add("identity"); tags.add("remote-first"); }
414
+ if (n === "cybereason") { tags.add("security"); tags.add("us"); }
415
+ if (n === "darktrace") { tags.add("security"); tags.add("uk"); }
416
+ if (n === "check point") { tags.add("security"); tags.add("israel"); }
417
+
418
+ // Fintech
419
+ if (n === "stripe") { tags.add("fintech"); tags.add("developer-tools"); tags.add("us"); }
420
+ if (n === "plaid") { tags.add("fintech"); tags.add("developer-tools"); tags.add("us"); }
421
+ if (n === "brex") { tags.add("fintech"); tags.add("us"); }
422
+ if (n === "ramp") { tags.add("fintech"); tags.add("us"); }
423
+ if (n === "mercury") { tags.add("fintech"); tags.add("remote-first"); }
424
+ if (n === "wise") { tags.add("fintech"); tags.add("uk"); }
425
+ if (n === "revolut") { tags.add("fintech"); tags.add("uk"); }
426
+ if (n === "monzo") { tags.add("fintech"); tags.add("uk"); }
427
+ if (n === "n26") { tags.add("fintech"); tags.add("eu"); }
428
+ if (n === "adyen") { tags.add("fintech"); tags.add("eu"); }
429
+ if (n === "checkout.com") { tags.add("fintech"); tags.add("uk"); }
430
+ if (n === "affirm") { tags.add("fintech"); tags.add("remote-first"); }
431
+ if (n === "robinhood") { tags.add("fintech"); tags.add("us"); }
432
+ if (n === "coinbase") { tags.add("fintech"); tags.add("us"); }
433
+ if (n.includes("square") || n.includes("block")) { tags.add("fintech"); tags.add("us"); }
434
+ if (n === "klarna") { tags.add("fintech"); tags.add("eu"); }
435
+ if (n === "razorpay") { tags.add("fintech"); tags.add("apac"); }
436
+
437
+ // Design / collaboration
438
+ if (n === "figma") { tags.add("collaboration"); tags.add("developer-tools"); tags.add("us"); }
439
+ if (n === "miro") { tags.add("collaboration"); tags.add("eu"); }
440
+ if (n === "canva") { tags.add("ai-creative"); tags.add("collaboration"); tags.add("apac"); }
441
+
442
+ // HR
443
+ if (n === "deel") { tags.add("hr-tech"); tags.add("remote-first"); }
444
+ if (n === "rippling") { tags.add("hr-tech"); tags.add("automation"); tags.add("us"); }
445
+ if (n === "factorial") { tags.add("hr-tech"); tags.add("eu"); }
446
+ if (n === "personio") { tags.add("hr-tech"); tags.add("eu"); }
447
+ if (n === "workday") { tags.add("hr-tech"); tags.add("enterprise-saas"); tags.add("us"); }
448
+
449
+ // Enterprise SaaS / Productivity
450
+ if (n === "servicenow") { tags.add("enterprise-saas"); tags.add("ai-agents"); tags.add("us"); }
451
+ if (n === "atlassian") { tags.add("productivity"); tags.add("collaboration"); tags.add("apac"); }
452
+ if (n === "asana") { tags.add("productivity"); tags.add("us"); }
453
+ if (n === "monday.com") { tags.add("productivity"); tags.add("israel"); }
454
+ if (n === "clickup") { tags.add("productivity"); tags.add("us"); }
455
+ if (n === "coda") { tags.add("productivity"); tags.add("us"); }
456
+ if (n === "glean") { tags.add("ai-search"); tags.add("enterprise-saas"); tags.add("us"); }
457
+
458
+ // CRM & Sales
459
+ if (n === "hubspot") { tags.add("crm"); tags.add("us"); }
460
+ if (n === "zendesk") { tags.add("crm"); tags.add("conversational-ai"); tags.add("us"); }
461
+ if (n === "freshworks") { tags.add("crm"); tags.add("apac"); }
462
+ if (n === "attio") { tags.add("crm"); tags.add("eu"); }
463
+ if (n === "clay") { tags.add("automation"); tags.add("crm"); tags.add("us"); }
464
+ if (n === "apollo.io") { tags.add("crm"); tags.add("us"); }
465
+ if (n === "outreach") { tags.add("crm"); tags.add("us"); }
466
+ if (n === "salesloft") { tags.add("crm"); tags.add("us"); }
467
+ if (n === "zoominfo") { tags.add("crm"); tags.add("us"); }
468
+ if (n === "clari") { tags.add("crm"); tags.add("us"); }
469
+ if (n === "6sense") { tags.add("crm"); tags.add("us"); }
470
+
471
+ // AI creative / marketing
472
+ if (n === "jasper") { tags.add("ai-creative"); tags.add("us"); }
473
+ if (n === "copy.ai") { tags.add("ai-creative"); tags.add("automation"); tags.add("us"); }
474
+ if (n === "runway") { tags.add("ai-creative"); tags.add("us"); }
475
+ if (n === "midjourney") { tags.add("ai-creative"); tags.add("us"); }
476
+ if (n === "pika") { tags.add("ai-creative"); tags.add("us"); }
477
+ if (n === "luma ai") { tags.add("ai-creative"); tags.add("us"); }
478
+
479
+ // Comms
480
+ if (n === "zoom") { tags.add("communication"); tags.add("us"); }
481
+ if (n.includes("slack")) { tags.add("communication"); tags.add("collaboration"); tags.add("us"); }
482
+ if (n === "discord") { tags.add("communication"); tags.add("us"); }
483
+ if (n === "loom") { tags.add("communication"); tags.add("collaboration"); tags.add("us"); }
484
+ if (n.includes("vonage")) { tags.add("communication"); tags.add("us"); }
485
+ if (n === "messagebird") { tags.add("communication"); tags.add("eu"); }
486
+ if (n === "sinch") { tags.add("communication"); tags.add("eu"); }
487
+
488
+ // E-commerce
489
+ if (n === "shopify") { tags.add("e-commerce"); tags.add("remote-first"); }
490
+ if (n === "instacart") { tags.add("e-commerce"); tags.add("logistics"); tags.add("us"); }
491
+ if (n === "doordash") { tags.add("e-commerce"); tags.add("logistics"); tags.add("us"); }
492
+ if (n === "etsy") { tags.add("e-commerce"); tags.add("us"); }
493
+ if (n === "faire") { tags.add("e-commerce"); tags.add("remote-first"); }
494
+ if (n === "zalando") { tags.add("e-commerce"); tags.add("eu"); }
495
+
496
+ // Travel
497
+ if (n === "airbnb") { tags.add("travel"); tags.add("us"); }
498
+ if (n === "uber") { tags.add("travel"); tags.add("logistics"); tags.add("us"); }
499
+ if (n === "lyft") { tags.add("travel"); tags.add("us"); }
500
+ if (n === "booking.com") { tags.add("travel"); tags.add("eu"); }
501
+ if (n === "travelperk") { tags.add("travel"); tags.add("eu"); }
502
+ if (n === "blablacar") { tags.add("travel"); tags.add("eu"); }
503
+
504
+ // Autonomous / Robotics
505
+ if (n === "waymo") { tags.add("autonomous"); tags.add("us"); }
506
+ if (n === "aurora") { tags.add("autonomous"); tags.add("us"); }
507
+ if (n === "nuro") { tags.add("autonomous"); tags.add("us"); }
508
+ if (n === "zoox") { tags.add("autonomous"); tags.add("us"); }
509
+ if (n === "cruise") { tags.add("autonomous"); tags.add("us"); }
510
+ if (n === "anduril") { tags.add("defense"); tags.add("autonomous"); tags.add("us"); }
511
+ if (n === "shield ai") { tags.add("defense"); tags.add("autonomous"); tags.add("us"); }
512
+ if (n === "figure ai") { tags.add("robotics"); tags.add("us"); }
513
+ if (n === "covariant") { tags.add("robotics"); tags.add("us"); }
514
+ if (n === "boston dynamics") { tags.add("robotics"); tags.add("us"); }
515
+ if (n === "built robotics") { tags.add("robotics"); tags.add("autonomous"); tags.add("construction"); tags.add("us"); }
516
+ if (n === "samsara") { tags.add("logistics"); tags.add("us"); }
517
+
518
+ // Healthcare
519
+ if (n === "tempus ai") { tags.add("healthcare"); tags.add("us"); }
520
+ if (n === "pathai") { tags.add("healthcare"); tags.add("us"); }
521
+ if (n === "insitro") { tags.add("healthcare"); tags.add("us"); }
522
+ if (n === "recursion") { tags.add("healthcare"); tags.add("us"); }
523
+ if (n === "viz.ai") { tags.add("healthcare"); tags.add("us"); }
524
+ if (n === "oscar health") { tags.add("healthcare"); tags.add("us"); }
525
+ if (n === "flatiron health") { tags.add("healthcare"); tags.add("us"); }
526
+ if (n === "hippocratic ai") { tags.add("healthcare"); tags.add("ai-lab"); tags.add("us"); }
527
+ if (n === "doctolib") { tags.add("healthcare"); tags.add("eu"); }
528
+
529
+ // Legal
530
+ if (n.includes("casetext")) { tags.add("legal-tech"); tags.add("us"); }
531
+ if (n === "ironclad") { tags.add("legal-tech"); tags.add("us"); }
532
+ if (n === "docusign") { tags.add("legal-tech"); tags.add("enterprise-saas"); tags.add("us"); }
533
+ if (n === "harvey") { tags.add("legal-tech"); tags.add("ai-agents"); tags.add("us"); }
534
+
535
+ // Data / ML platform
536
+ if (n === "dbt labs") { tags.add("analytics"); tags.add("developer-tools"); tags.add("remote-first"); }
537
+ if (n === "fivetran") { tags.add("analytics"); tags.add("us"); }
538
+ if (n === "airbyte") { tags.add("analytics"); tags.add("open-source"); tags.add("us"); }
539
+ if (n === "dagster") { tags.add("analytics"); tags.add("developer-tools"); tags.add("us"); }
540
+ if (n === "prefect") { tags.add("analytics"); tags.add("developer-tools"); tags.add("us"); }
541
+ if (n === "hex") { tags.add("analytics"); tags.add("us"); }
542
+ if (n === "census") { tags.add("analytics"); tags.add("us"); }
543
+ if (n === "posthog") { tags.add("analytics"); tags.add("open-source"); tags.add("remote-first"); }
544
+
545
+ // DevOps / infra
546
+ if (n === "hashicorp") { tags.add("devops"); tags.add("cloud"); tags.add("us"); }
547
+ if (n === "pulumi") { tags.add("devops"); tags.add("open-source"); tags.add("us"); }
548
+ if (n === "fly.io") { tags.add("cloud"); tags.add("developer-tools"); tags.add("remote-first"); }
549
+ if (n === "render") { tags.add("cloud"); tags.add("developer-tools"); tags.add("us"); }
550
+ if (n === "launchdarkly") { tags.add("developer-tools"); tags.add("us"); }
551
+ if (n === "stytch") { tags.add("identity"); tags.add("developer-tools"); tags.add("us"); }
552
+ if (n === "workos") { tags.add("identity"); tags.add("developer-tools"); tags.add("us"); }
553
+ if (n === "jfrog") { tags.add("devops"); tags.add("us"); }
554
+ if (n === "circleci") { tags.add("devops"); tags.add("us"); }
555
+ if (n === "buildkite") { tags.add("devops"); tags.add("remote-first"); }
556
+ if (n === "kong") { tags.add("devops"); tags.add("networking"); tags.add("us"); }
557
+ if (n === "postman") { tags.add("developer-tools"); tags.add("us"); }
558
+ if (n === "fastly") { tags.add("cloud"); tags.add("networking"); tags.add("us"); }
559
+ if (n === "netlify") { tags.add("developer-tools"); tags.add("remote-first"); }
560
+ if (n === "docker") { tags.add("devops"); tags.add("developer-tools"); tags.add("us"); }
561
+ if (n === "digitalocean") { tags.add("cloud"); tags.add("us"); }
562
+ if (n === "akamai") { tags.add("cloud"); tags.add("networking"); tags.add("us"); }
563
+
564
+ // Analytics & BI
565
+ if (n === "thoughtspot") { tags.add("analytics"); tags.add("ai-search"); tags.add("us"); }
566
+ if (n === "amplitude") { tags.add("analytics"); tags.add("us"); }
567
+ if (n === "mixpanel") { tags.add("analytics"); tags.add("us"); }
568
+ if (n.includes("segment")) { tags.add("analytics"); tags.add("us"); }
569
+ if (n === "heap") { tags.add("analytics"); tags.add("us"); }
570
+ if (n === "metabase") { tags.add("analytics"); tags.add("open-source"); tags.add("us"); }
571
+ if (n.includes("preset")) { tags.add("analytics"); tags.add("open-source"); tags.add("us"); }
572
+ if (n === "observable") { tags.add("analytics"); tags.add("developer-tools"); tags.add("us"); }
573
+ if (n === "hightouch") { tags.add("analytics"); tags.add("us"); }
574
+ if (n === "contentsquare") { tags.add("analytics"); tags.add("eu"); }
575
+
576
+ // AI Agents
577
+ if (n === "relevance ai") { tags.add("ai-agents"); tags.add("apac"); }
578
+ if (n === "fixie ai") { tags.add("ai-agents"); tags.add("developer-tools"); tags.add("us"); }
579
+ if (n === "dust") { tags.add("ai-agents"); tags.add("eu"); }
580
+ if (n === "moveworks") { tags.add("ai-agents"); tags.add("enterprise-saas"); tags.add("us"); }
581
+ if (n === "adept ai") { tags.add("ai-agents"); tags.add("us"); }
582
+ if (n === "voiceflow") { tags.add("conversational-ai"); tags.add("no-code"); tags.add("us"); }
583
+ if (n === "tray.io") { tags.add("automation"); tags.add("enterprise-saas"); tags.add("us"); }
584
+ if (n === "workato") { tags.add("automation"); tags.add("enterprise-saas"); tags.add("us"); }
585
+
586
+ // European
587
+ if (n === "tinybird") { tags.add("analytics"); tags.add("developer-tools"); tags.add("remote-first"); }
588
+ if (n === "clarity ai") { tags.add("analytics"); tags.add("climate"); tags.add("eu"); }
589
+ if (n === "dataiku") { tags.add("mlops"); tags.add("eu"); }
590
+ if (n === "algolia") { tags.add("ai-search"); tags.add("developer-tools"); tags.add("eu"); }
591
+ if (n === "snorkel ai") { tags.add("mlops"); tags.add("us"); }
592
+ if (n === "collibra") { tags.add("analytics"); tags.add("compliance"); tags.add("eu"); }
593
+ if (n === "celonis") { tags.add("automation"); tags.add("analytics"); tags.add("eu"); }
594
+ if (n === "uipath") { tags.add("rpa"); tags.add("automation"); tags.add("eu"); }
595
+ if (n === "typeform") { tags.add("enterprise-saas"); tags.add("eu"); }
596
+ if (n === "pitch") { tags.add("productivity"); tags.add("eu"); }
597
+
598
+ // Israel
599
+ if (n === "wix") { tags.add("developer-tools"); tags.add("no-code"); tags.add("israel"); }
600
+ if (n === "taboola") { tags.add("media"); tags.add("israel"); }
601
+
602
+ // EdTech
603
+ if (n === "duolingo") { tags.add("edtech"); tags.add("us"); }
604
+ if (n === "coursera") { tags.add("edtech"); tags.add("us"); }
605
+ if (n === "khan academy") { tags.add("edtech"); tags.add("us"); }
606
+ if (n === "chegg") { tags.add("edtech"); tags.add("us"); }
607
+
608
+ // Gaming
609
+ if (n === "unity") { tags.add("gaming"); tags.add("developer-tools"); tags.add("us"); }
610
+ if (n === "epic games") { tags.add("gaming"); tags.add("developer-tools"); tags.add("us"); }
611
+ if (n === "roblox") { tags.add("gaming"); tags.add("ai-creative"); tags.add("us"); }
612
+
613
+ // Climate
614
+ if (n === "climavision") { tags.add("climate"); tags.add("us"); }
615
+ if (n === "watershed") { tags.add("climate"); tags.add("us"); }
616
+ if (n === "arcadia") { tags.add("climate"); tags.add("us"); }
617
+
618
+ // Logistics
619
+ if (n === "flexport") { tags.add("logistics"); tags.add("us"); }
620
+ if (n === "project44") { tags.add("logistics"); tags.add("us"); }
621
+ if (n === "fourkites") { tags.add("logistics"); tags.add("us"); }
622
+
623
+ // Real estate
624
+ if (n === "opendoor") { tags.add("real-estate"); tags.add("us"); }
625
+ if (n === "zillow") { tags.add("real-estate"); tags.add("us"); }
626
+
627
+ // Telecom
628
+ if (n.includes("starlink") || n.includes("spacex")) { tags.add("networking"); tags.add("us"); }
629
+
630
+ // Music / Media
631
+ if (n === "spotify") { tags.add("media"); tags.add("eu"); }
632
+
633
+ // Insurance
634
+ if (n === "lemonade") { tags.add("insurance"); tags.add("us"); }
635
+ if (n === "tractable") { tags.add("insurance"); tags.add("uk"); }
636
+
637
+ // Identity
638
+ if (n === "persona") { tags.add("identity"); tags.add("us"); }
639
+ if (n === "jumio") { tags.add("identity"); tags.add("us"); }
640
+ if (n === "onfido") { tags.add("identity"); tags.add("uk"); }
641
+
642
+ // Networking
643
+ if (n === "tailscale") { tags.add("networking"); tags.add("remote-first"); }
644
+ if (n === "cloudinary") { tags.add("developer-tools"); tags.add("israel"); }
645
+ if (n === "imgix") { tags.add("developer-tools"); tags.add("us"); }
646
+
647
+ // Testing
648
+ if (n === "browserstack") { tags.add("testing"); tags.add("apac"); }
649
+ if (n === "sauce labs") { tags.add("testing"); tags.add("us"); }
650
+ if (n.includes("testim")) { tags.add("testing"); tags.add("us"); }
651
+
652
+ // Open source
653
+ if (n === "gitpod") { tags.add("developer-tools"); tags.add("open-source"); tags.add("remote-first"); }
654
+ if (n === "coder") { tags.add("developer-tools"); tags.add("open-source"); tags.add("remote-first"); }
655
+ if (n === "meilisearch") { tags.add("ai-search"); tags.add("open-source"); tags.add("eu"); }
656
+ if (n === "minio") { tags.add("cloud"); tags.add("open-source"); tags.add("us"); }
657
+
658
+ // Media / Content
659
+ if (n === "reddit") { tags.add("media"); tags.add("us"); }
660
+ if (n === "pinterest") { tags.add("media"); tags.add("e-commerce"); tags.add("us"); }
661
+ if (n === "snap") { tags.add("media"); tags.add("ai-creative"); tags.add("us"); }
662
+ if (n.includes("new york times")) { tags.add("media"); tags.add("us"); }
663
+ if (n === "substack") { tags.add("media"); tags.add("us"); }
664
+ if (n === "twitch") { tags.add("media"); tags.add("gaming"); tags.add("us"); }
665
+
666
+ // Food
667
+ if (n === "toast") { tags.add("food-tech"); tags.add("us"); }
668
+ if (n.includes("grubhub")) { tags.add("food-tech"); tags.add("logistics"); tags.add("us"); }
669
+
670
+ // Gov / defense
671
+ if (n === "govini") { tags.add("govtech"); tags.add("defense"); tags.add("us"); }
672
+ if (n === "primer ai") { tags.add("govtech"); tags.add("defense"); tags.add("us"); }
673
+
674
+ // Misc
675
+ if (n === "grammarly") { tags.add("ai-creative"); tags.add("remote-first"); }
676
+ if (n === "webflow") { tags.add("no-code"); tags.add("developer-tools"); tags.add("us"); }
677
+ if (n === "palantir") { tags.add("analytics"); tags.add("defense"); tags.add("us"); }
678
+ if (n === "weights & biases") { tags.add("mlops"); tags.add("us"); }
679
+ if (n === "red hat") { tags.add("cloud"); tags.add("open-source"); tags.add("us"); }
680
+ if (n === "suse") { tags.add("cloud"); tags.add("open-source"); tags.add("eu"); }
681
+ if (n === "canonical") { tags.add("cloud"); tags.add("open-source"); tags.add("remote-first"); }
682
+ if (n.includes("isovalent")) { tags.add("networking"); tags.add("open-source"); tags.add("us"); }
683
+ if (n === "worldcoin") { tags.add("identity"); tags.add("us"); }
684
+ if (n === "pagerduty") { tags.add("observability"); tags.add("us"); }
685
+ if (n === "firehydrant") { tags.add("observability"); tags.add("us"); }
686
+ if (n === "rootly") { tags.add("observability"); tags.add("us"); }
687
+ if (n === "vanta") { tags.add("compliance"); tags.add("security"); tags.add("us"); }
688
+ if (n === "drata") { tags.add("compliance"); tags.add("us"); }
689
+ if (n === "chainguard") { tags.add("security"); tags.add("open-source"); tags.add("us"); }
690
+ if (n === "teleport") { tags.add("security"); tags.add("developer-tools"); tags.add("us"); }
691
+ if (n === "liveblocks") { tags.add("collaboration"); tags.add("developer-tools"); tags.add("us"); }
692
+ if (n === "convex") { tags.add("developer-tools"); tags.add("database"); tags.add("us"); }
693
+ if (n === "railway") { tags.add("cloud"); tags.add("developer-tools"); tags.add("us"); }
694
+ if (n === "deno") { tags.add("developer-tools"); tags.add("open-source"); tags.add("us"); }
695
+ if (n === "val town") { tags.add("developer-tools"); tags.add("us"); }
696
+ if (n === "sanity") { tags.add("developer-tools"); tags.add("us"); }
697
+ if (n === "contentful") { tags.add("developer-tools"); tags.add("eu"); }
698
+ if (n === "storyblok") { tags.add("developer-tools"); tags.add("eu"); }
699
+ if (n === "redpanda") { tags.add("developer-tools"); tags.add("open-source"); tags.add("us"); }
700
+ if (n === "warpstream") { tags.add("developer-tools"); tags.add("us"); }
701
+ if (n === "buf") { tags.add("developer-tools"); tags.add("us"); }
702
+ if (n === "hasura") { tags.add("developer-tools"); tags.add("open-source"); tags.add("us"); }
703
+ if (n === "prisma") { tags.add("developer-tools"); tags.add("open-source"); tags.add("eu"); }
704
+ if (n === "drizzle") { tags.add("developer-tools"); tags.add("open-source"); tags.add("remote-first"); }
705
+ if (n === "grafbase") { tags.add("developer-tools"); tags.add("eu"); }
706
+ if (n === "gitguardian") { tags.add("security"); tags.add("developer-tools"); tags.add("eu"); }
707
+ if (n === "doppler") { tags.add("security"); tags.add("developer-tools"); tags.add("us"); }
708
+ if (n === "resend") { tags.add("developer-tools"); tags.add("us"); }
709
+ if (n === "inngest") { tags.add("developer-tools"); tags.add("us"); }
710
+ if (n === "trigger.dev") { tags.add("developer-tools"); tags.add("us"); }
711
+ if (n === "nango") { tags.add("developer-tools"); tags.add("us"); }
712
+ if (n === "svix") { tags.add("developer-tools"); tags.add("us"); }
713
+ if (n === "comet ml") { tags.add("mlops"); tags.add("us"); }
714
+ if (n === "neptune.ai") { tags.add("mlops"); tags.add("eu"); }
715
+ if (n.includes("determined ai")) { tags.add("mlops"); tags.add("us"); }
716
+ if (n === "labelbox") { tags.add("mlops"); tags.add("us"); }
717
+ if (n === "humanloop") { tags.add("llmops"); tags.add("uk"); }
718
+ if (n === "eigen technologies") { tags.add("fintech"); tags.add("uk"); }
719
+ if (n === "featurespace") { tags.add("fintech"); tags.add("security"); tags.add("uk"); }
720
+ if (n === "procore") { tags.add("construction"); tags.add("us"); }
721
+ if (n === "veeva systems") { tags.add("healthcare"); tags.add("enterprise-saas"); tags.add("remote-first"); }
722
+ if (n === "coactive ai") { tags.add("ai-search"); tags.add("us"); }
723
+ if (n === "you.com") { tags.add("ai-search"); tags.add("us"); }
724
+ if (n === "hebbia") { tags.add("ai-search"); tags.add("fintech"); tags.add("us"); }
725
+
726
+ // ── Region from notes ──
727
+
728
+ const notesLower = notes.toLowerCase();
729
+ if (has(notesLower, "remote-first") || has(notesLower, "remote first") || (has(notesLower, "remote") && has(notesLower, "friendly"))) {
730
+ tags.add("remote-first");
731
+ }
732
+ if (has(notesLower, "tel aviv") || has(notesLower, "israel")) tags.add("israel");
733
+ if (has(notesLower, "berlin") || has(notesLower, "munich") || has(notesLower, "paris") || has(notesLower, "amsterdam") ||
734
+ has(notesLower, "barcelona") || has(notesLower, "madrid") || has(notesLower, "lisbon") ||
735
+ has(notesLower, "dusseldorf") || has(notesLower, "düsseldorf") || has(notesLower, "heidelberg") ||
736
+ has(notesLower, "nuremberg") || has(notesLower, "brussels") || has(notesLower, "tallinn") ||
737
+ has(notesLower, "bucharest") || has(notesLower, "linz") || has(notesLower, "warsaw") ||
738
+ has(notesLower, "walldorf") || has(notesLower, "stockholm") ||
739
+ has(notesLower, "european") || has(notesLower, "emea")) {
740
+ tags.add("eu");
741
+ }
742
+ if (has(notesLower, "london") || has(notesLower, "cambridge uk") || has(notesLower, "uk.") || has(notesLower, "uk ") ||
743
+ notesLower.endsWith("uk") || has(notesLower, "dublin")) {
744
+ tags.add("uk");
745
+ }
746
+ if (has(notesLower, "sydney") || has(notesLower, "bangalore") || has(notesLower, "chennai") || has(notesLower, "tokyo") ||
747
+ has(notesLower, "singapore")) {
748
+ tags.add("apac");
749
+ }
750
+
751
+ // ── Ensure at least one region tag ──
752
+ const regionTags = ["us", "eu", "uk", "apac", "israel", "remote-first"];
753
+ if (!regionTags.some((r) => tags.has(r))) {
754
+ // Default to US for companies without explicit location
755
+ tags.add("us");
756
+ }
757
+
758
+ // ── Cap at 5 tags, ensure at least 2 ──
759
+ let result = [...tags];
760
+
761
+ // If we have more than 5 tags, prioritize: keep region, then industry/platform
762
+ if (result.length > 5) {
763
+ const regions = result.filter((t) => regionTags.includes(t));
764
+ const nonRegions = result.filter((t) => !regionTags.includes(t));
765
+ // Keep 1 region + up to 4 non-region
766
+ const keepRegions = regions.slice(0, 1);
767
+ const keepOther = nonRegions.slice(0, 4);
768
+ result = [...keepOther, ...keepRegions];
769
+ }
770
+
771
+ return result;
772
+ }
773
+
774
+ // ── Main ─────────────────────────────────────────────────────────────────
775
+
776
+ const raw = readFileSync(FILE, "utf8");
777
+ const lines = raw.split("\n");
778
+
779
+ const out = [];
780
+ let currentSection = "";
781
+ let companyName = "";
782
+ let companyNotes = "";
783
+ let inTrackedCompanies = false;
784
+
785
+ // We need two passes: first collect company info, then insert tags.
786
+ // Since we're line-by-line and a company block looks like:
787
+ // - name: Foo
788
+ // careers_url: ...
789
+ // [api: ...]
790
+ // [notes: ...]
791
+ // enabled: true/false
792
+ //
793
+ // We buffer lines until we hit `enabled:`, compute tags, insert, then flush.
794
+
795
+ let buffer = [];
796
+ let seenTags = false; // does current company already have tags?
797
+
798
+ function flushWithTags() {
799
+ if (buffer.length === 0) return;
800
+
801
+ // Find the `enabled:` line and company context
802
+ const enabledIdx = buffer.findIndex((l) => l.match(/^\s+enabled:/));
803
+ if (enabledIdx === -1 || !inTrackedCompanies || seenTags) {
804
+ // No enabled line or already has tags or not in tracked_companies -- pass through
805
+ out.push(...buffer);
806
+ buffer = [];
807
+ seenTags = false;
808
+ return;
809
+ }
810
+
811
+ const tags = assignTags(currentSection, companyName, companyNotes);
812
+ const indent = buffer[enabledIdx].match(/^(\s*)/)[1]; // match indentation
813
+ const tagLine = `${indent}tags: [${tags.map((t) => `"${t}"`).join(", ")}]`;
814
+
815
+ // Insert tag line before enabled line
816
+ buffer.splice(enabledIdx, 0, tagLine);
817
+ out.push(...buffer);
818
+ buffer = [];
819
+ seenTags = false;
820
+ }
821
+
822
+ for (let i = 0; i < lines.length; i++) {
823
+ const line = lines[i];
824
+
825
+ // Detect tracked_companies section
826
+ if (line.match(/^tracked_companies:/)) {
827
+ inTrackedCompanies = true;
828
+ out.push(line);
829
+ continue;
830
+ }
831
+
832
+ if (!inTrackedCompanies) {
833
+ out.push(line);
834
+ continue;
835
+ }
836
+
837
+ // Detect section comments like "# -- AI Labs & LLM providers --"
838
+ const sectionMatch = line.match(/^\s*#\s*--\s*(.+?)\s*--/);
839
+ if (sectionMatch) {
840
+ flushWithTags();
841
+ currentSection = sectionMatch[1];
842
+ out.push(line);
843
+ continue;
844
+ }
845
+
846
+ // Detect start of new company entry
847
+ const nameMatch = line.match(/^\s+-\s+name:\s*(.+)/);
848
+ if (nameMatch) {
849
+ flushWithTags();
850
+ companyName = nameMatch[1].trim();
851
+ companyNotes = "";
852
+ seenTags = false;
853
+ buffer.push(line);
854
+ continue;
855
+ }
856
+
857
+ // Collect notes
858
+ const notesMatch = line.match(/^\s+notes:\s*"?(.+)"?\s*$/);
859
+ if (notesMatch) {
860
+ companyNotes = notesMatch[1].replace(/^"|"$/g, "");
861
+ buffer.push(line);
862
+ continue;
863
+ }
864
+
865
+ // Check if company already has tags
866
+ if (line.match(/^\s+tags:/)) {
867
+ seenTags = true;
868
+ buffer.push(line);
869
+ continue;
870
+ }
871
+
872
+ // On `enabled:` line, add it to buffer then flush (tags get inserted before it)
873
+ if (line.match(/^\s+enabled:/)) {
874
+ buffer.push(line);
875
+ flushWithTags();
876
+ continue;
877
+ }
878
+
879
+ // Other lines inside a company block (api:, careers_url:, scan_method:, etc.)
880
+ if (buffer.length > 0) {
881
+ buffer.push(line);
882
+ continue;
883
+ }
884
+
885
+ // Blank lines and other comments between companies
886
+ out.push(line);
887
+ }
888
+
889
+ // Flush any remaining buffer
890
+ flushWithTags();
891
+
892
+ writeFileSync(FILE, out.join("\n"), "utf8");
893
+
894
+ console.log("Done. Tags added to tracked companies in portals.example.yml");