chore: move cv and job applications to private rafapolo/job, add delivery-lead watcher

cv/ and jobs/ become symlinks into ../rafapolo/job (gitignored there).
scripts/watch-delivery-lead.ts runs daily via launchd and alerts on Telegram
when the MRP-Global agentic Delivery Lead role resurfaces or closes.
This commit is contained in:
2026-10-05 19:22:07 +02:00
parent dfba00ae91
commit 74f8df0b15
12 changed files with 189 additions and 810 deletions
+3 -5
View File
@@ -4,9 +4,7 @@ node_modules/
# job data and personal notes # job data and personal notes
results/ results/
jobs/ # symlinks into the private ../rafapolo/job/ (gitignored there too)
jobs
cv
# CV files (large binaries + personal)
cv/*.pdf
cv/*.odt
cv/*.html
+9 -2
View File
@@ -30,10 +30,10 @@ telegram.ts # Telegram delivery, chunking, --setup chat-ID discovery
scripts/ # one-off search scripts; import from ../config.ts and ../fetch.ts scripts/ # one-off search scripts; import from ../config.ts and ../fetch.ts
scripts/scicore-watch.sh # daily launchd watch on sciCORE's open-positions page scripts/scicore-watch.sh # daily launchd watch on sciCORE's open-positions page
results/sent.txt # links already pushed to Telegram — never sent twice results/sent.txt # links already pushed to Telegram — never sent twice
cv/ → ../rafapolo/job/cv/ # symlink; CVs (cv-source.md is canonical, polo.md is the ranking profile)
cv/polo.md # Rafael's profile — use for ranking jobs cv/polo.md # Rafael's profile — use for ranking jobs
cv/ # CV files (html, pdf, odt)
results/jobs.csv # output — one row per job results/jobs.csv # output — one row per job
jobs/ # notes on specific job leads jobs/ → ../rafapolo/job/applications/ # symlink; one folder per company: cover/motivation letters, dossiers, notes
plans/ # LinkedIn post drafts plans/ # LinkedIn post drafts
``` ```
@@ -178,6 +178,12 @@ Extra filters for temp scripts (import from `../fetch.ts`):
- `isEnglishContent(id)` — drop DE/FR description content - `isEnglishContent(id)` — drop DE/FR description content
- Add your own inline RE for EMEA, .NET, etc. - Add your own inline RE for EMEA, .NET, etc.
## Application history (`jobs/`, `cv/`)
`cv/` and `jobs/` are symlinks into the **private** `../rafapolo/job/` (gitignored in both repos; `rafapolo` is a public GitHub Pages site, so never move these into a non-ignored path there). Everything else about past applications lives beside them: `../rafapolo/job/career-strategy-notes.md`, `credentials/` (certs, diplomas, references) and the dossier PDFs at the root.
Before presenting a job or writing a letter, check `jobs/<company-slug>/` (e.g. `ls jobs | grep -i roche`): if a folder exists, Rafael already applied there — say so, reuse the earlier letter as a starting point, and mention any track record in memory (e.g. Adobe and BIS cold applies are dead). New letters go in `jobs/<company-slug>/`.
## Ranking jobs against the CV ## Ranking jobs against the CV
Read `cv/polo.md` for the full profile. Key signals: Read `cv/polo.md` for the full profile. Key signals:
@@ -216,6 +222,7 @@ Runs as a **launchd agent** — this machine has no cron at all, so don't reach
| plist (`~/Library/LaunchAgents/`) | when | runs | | plist (`~/Library/LaunchAgents/`) | when | runs |
|---|---|---| |---|---|---|
| `com.rafapolo.linkme-daily` | 09:00 / 12:00 / 15:00 / 17:00 / 20:00 | `bun run daily.ts` → `results/daily.log` | | `com.rafapolo.linkme-daily` | 09:00 / 12:00 / 15:00 / 17:00 / 20:00 | `bun run daily.ts` → `results/daily.log` |
| `com.rafapolo.linkme-watch-delivery-lead` | 10:00 | `bun run scripts/watch-delivery-lead.ts` → `results/watch-delivery-lead.log`; watches for the MRP-Global "Delivery Lead – Agentic Solutions" opening (LinkedIn 4473851998) resurfacing elsewhere and for the original closing. Telegram only on a hit. Unload once the lead is resolved |
If the Mac is asleep at the scheduled time, launchd fires the job on wake rather than skipping the day. `launchctl list | grep linkme` to check it's loaded; `launchctl unload <plist>` to stop it. If the Mac is asleep at the scheduled time, launchd fires the job on wake rather than skipping the day. `launchctl list | grep linkme` to check it's loaded; `launchctl unload <plist>` to stop it.
-234
View File
@@ -1,234 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Rafael Polo - CV</title>
<style>
@page {
size: 8.2681in 11.6929in;
margin: 0.5in;
}
body {
font-family: Calibri, Liberation Sans, sans-serif;
font-size: 11pt;
line-height: 1.2;
margin: 0;
padding: 0;
}
.container {
display: table;
width: 100%;
}
.left-col {
display: table-cell;
width: 100%;
}
.title {
font-size: 24pt;
font-weight: bold;
margin-bottom: 0.05in;
}
.subtitle {
font-size: 11pt;
font-style: italic;
margin-bottom: 0.15in;
color: #444;
}
table.personal {
width: 100%;
border-collapse: collapse;
margin-bottom: 0.2in;
}
table.personal td {
padding: 0.02in 0.05in;
vertical-align: top;
}
table.personal .label {
font-weight: bold;
color: #333;
width: 1in;
}
table.personal .header-row td {
font-weight: bold;
font-size: 11pt;
text-transform: uppercase;
border-bottom: 1px solid #999;
padding-bottom: 0.05in;
}
h3 {
font-size: 11pt;
font-weight: bold;
text-transform: uppercase;
letter-spacing: 0.05em;
margin: 0.15in 0 0.08in 0;
border-bottom: 1px solid #999;
padding-bottom: 0.03in;
}
ul {
margin: 0.05in 0;
padding-left: 0.15in;
}
li {
margin-bottom: 0.04in;
font-size: 10pt;
}
.job-item {
margin-bottom: 0.08in;
}
.job-title {
font-weight: bold;
font-size: 10pt;
}
.job-meta {
font-style: italic;
font-size: 9pt;
color: #555;
}
.job-desc {
font-style: italic;
font-size: 10pt;
color: #444;
margin-left: 0.1in;
}
.edu-item {
margin-bottom: 0.05in;
}
.edu-degree {
font-weight: bold;
font-size: 10pt;
}
.edu-school {
font-style: italic;
font-size: 10pt;
}
.skill-item {
font-size: 10pt;
margin-bottom: 0.02in;
}
.lang-item {
font-size: 10pt;
margin-bottom: 0.02in;
}
.footer {
font-size: 9pt;
color: #666;
margin-top: 0.2in;
padding-top: 0.1in;
border-top: 1px solid #ccc;
}
</style>
</head>
<body>
<div class="title">Rafael Polo</div>
<div class="subtitle">Senior Software Engineer — Platform, Data & AI</div>
<table class="personal">
<tr>
<td colspan="2" class="header-row">Personal</td>
</tr>
<tr>
<td class="label">First name:</td>
<td>Rafael</td>
</tr>
<tr>
<td class="label">Last name:</td>
<td>Polo</td>
</tr>
<tr>
<td class="label">Citizenship:</td>
<td>Portuguese (EU) · Brazilian — no work permit required</td>
</tr>
<tr>
<td class="label">Address:</td>
<td>Basel, 4055, Switzerland</td>
</tr>
<tr>
<td class="label">Email:</td>
<td>rafael@extrapolo.com</td>
</tr>
<tr>
<td class="label">Web:</td>
<td>linkedin.com/in/rafaelpolo<br>extrapolo.com</td>
</tr>
</table>
<h3>Formal Education</h3>
<ul>
<li class="edu-item">
<span class="edu-degree"><em><strong>Postgraduate in Data Science for Finance</strong></em> – 2021</span><br>
<span class="edu-school">NOVA IMS Information Management School, Lisbon</span>
</li>
<li class="edu-item">
<span class="edu-degree"><em><strong>Master in Information Systems</strong></em> – 2010–2012</span><br>
<span class="edu-school">PPGI/UNIRIO — Knowledge Representation & Reasoning</span>
</li>
<li class="edu-item">
<span class="edu-degree"><em><strong>Bachelor in Computer Science</strong></em> – 2004–2009</span><br>
<span class="edu-school">Metodista Bennett, Rio de Janeiro</span>
</li>
</ul>
<h3>Relevant Professional Experience</h3>
<ul>
<li class="job-item">
<span class="job-title">Swisscom</span> – <span class="job-meta">2024–2025 – Zürich, Switzerland</span><br>
<span class="job-desc"><strong>DevOps Engineer</strong> developing platforms for Telecommunication Operations.</span>
</li>
<li class="job-item">
<span class="job-title">EDGE Empower®</span> – <span class="job-meta">2024–2025 – Baar, Switzerland</span><br>
<span class="job-desc"><strong>Senior Technical Lead</strong> managing projects and external UX & Dev Teams for a SaaS Product.</span>
</li>
<li class="job-item">
<span class="job-title">ExtraPolo — Independent Consulting</span> – <span class="job-meta">2010–2022 – Rio de Janeiro · Berlin · Athens · Lisbon</span><br>
<span class="job-desc">40+ projects across civic tech, data journalism, open-source platforms and interactive installations for public and private clients.</span>
</li>
<li class="job-item">
<span class="job-title">Moedax Digital Services</span> – <span class="job-meta">2018–2021 – Lisbon · Rio de Janeiro</span><br>
<span class="job-desc"><strong>Founder & CTO</strong> – Fintech startup connecting CBDC digital currency with KYC compliance automation.</span>
</li>
<li class="job-item">
<span class="job-title">GFOSS.eu / Code + Create</span> – <span class="job-meta">2017–2018 – Athens, Greece</span><br>
<span class="job-desc"><strong>Web Programming Teacher</strong> – taught HTML, CSS, jQuery to refugee and local youth.</span>
</li>
<li class="job-item">
<span class="job-title">Tactical Tech Collective</span> – <span class="job-meta">2014–2016 – Berlin, Germany</span><br>
<span class="job-desc"><strong>Full-Stack Web Architect</strong> – investigative data tools under Exposing the Invisible team.</span>
</li>
<li class="job-item">
<span class="job-title">Trommsdorf + Drüner</span> – <span class="job-meta">2013–2014 – Berlin, Germany</span><br>
<span class="job-desc"><strong>Full-Stack Engineer</strong> – Innovation Team developing Business Intelligence dashboards.</span>
</li>
<li class="job-item">
<span class="job-title">Cortex Intelligence</span> – <span class="job-meta">2007–2008 – Rio de Janeiro, Brazil</span><br>
<span class="job-desc"><strong>Developer</strong> – Competitive Intelligence and Data Mining R&D team.</span>
</li>
</ul>
<h3>Certifications</h3>
<ul>
<li class="skill-item">Swiss Federal Act on Data Protection (nFADP)</li>
<li class="skill-item">Gen AI Foundational Models — NLP & LLMs</li>
<li class="skill-item">AI Agents using RAG and LangChain</li>
</ul>
<h3>Relevant Tech Skills</h3>
<ul>
<li class="skill-item"><strong>Languages & Frameworks:</strong> Python · Ruby on Rails · TypeScript · React · Java</li>
<li class="skill-item"><strong>DevOps & Infra:</strong> Docker · Kubernetes · CI/CD · AWS · Linux · Git</li>
<li class="skill-item"><strong>Data & AI:</strong> SQL · ETL · Data Engineering · RAG · LangChain · LLM integrations</li>
<li class="skill-item"><strong>Architecture:</strong> REST APIs · MVC · OOP · UML · System Design · Web Crawling</li>
</ul>
<h3>Natural Languages</h3>
<ul>
<li class="lang-item">Native Brazilian Portuguese</li>
<li class="lang-item">Full professional English</li>
<li class="lang-item">Full professional Spanish</li>
<li class="lang-item">German B1 – TELC certified · 3 yrs Berlin + 3 yrs Basel</li>
</ul>
<div class="footer">
References available upon request · CV updated May 2026
</div>
</body>
</html>
-196
View File
@@ -1,196 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Rafael Polo - CV</title>
<style>
@page {
size: 8.2681in 11.6929in;
margin: 0.5in;
}
body {
font-family: Liberation Sans, Carlito, Georgia, serif;
font-size: 11pt;
line-height: 1.4;
margin: 0;
padding: 0;
}
.title {
font-size: 36pt;
font-weight: bold;
margin-bottom: 0.1in;
}
.subtitle {
font-size: 14pt;
margin-bottom: 0.3in;
color: #333;
}
h1 {
font-size: 24pt;
font-weight: bold;
margin: 0.2in 0 0.1in 0;
border-bottom: 1px solid #333;
padding-bottom: 0.05in;
}
h2 {
font-size: 18pt;
font-weight: bold;
margin: 0.15in 0 0.08in 0;
}
h3 {
font-size: 14pt;
font-weight: bold;
margin: 0.1in 0 0.05in 0;
}
.section {
margin-bottom: 0.15in;
}
.personalinline {
font-size: 10pt;
margin-bottom: 0.2in;
}
.personalinline span {
margin-right: 0.3in;
}
.key-value {
display: flex;
margin: 0.03in 0;
}
.key {
font-weight: bold;
width: 1.5in;
}
.value {
flex: 1;
}
ul {
margin: 0.05in 0;
padding-left: 0.2in;
}
li {
margin-bottom: 0.03in;
}
.small {
font-size: 10pt;
}
.experience-item {
margin-bottom: 0.1in;
}
.exp-header {
font-weight: bold;
}
.exp-meta {
font-style: italic;
font-size: 10pt;
}
.exp-desc {
margin-left: 0.2in;
}
</style>
</head>
<body>
<div class="title">Rafael Polo</div>
<div class="subtitle">Senior Software Engineer — Platform, Data & AI</div>
<div class="personalinline">
<span>Basel, 4055, Switzerland</span>
<span>rafael@extrapolo.com</span>
<span>linkedin.com/in/rafaelpolo</span>
<span>extrapolo.com</span>
</div>
<div class="personalinline">
<span>Portuguese (EU) · Brazilian — no work permit required</span>
<span>20+ years building production systems across Switzerland, Germany, Greece and Brazil</span>
<span>Fluent English · German B1 TELC (3 yrs Berlin + 3 yrs Basel) · EU citizen, immediately available</span>
</div>
<div class="section">
<h1>P R O F E S S I O N A L E X P E R I E N C E</h1>
<div class="experience-item">
<div class="exp-header">Swisscom</div>
<div class="exp-meta">DevOps Engineer · Zürich, Switzerland</div>
<div class="exp-desc">Modernization of mission-critical internal platforms & CI/CD pipelines for high-availability Telecom infrastructure.</div>
</div>
<div class="experience-item">
<div class="exp-header">EDGE Empower®</div>
<div class="exp-meta">Senior Technical Lead · Baar, Switzerland · 2024 – 2025</div>
<div class="exp-desc">Built a PayTool cutting processing time by 98%; reduced CI/CD pipeline from 14 → 4 minutes; managed 3 developers and a UX designer for a SaaS product.</div>
</div>
<div class="experience-item">
<div class="exp-header">ExtraPolo — Independent Consulting</div>
<div class="exp-meta">Software Engineer & Consultant · Rio de Janeiro · Berlin · Athens · Lisbon · 2010 – 2022</div>
<div class="exp-desc">40+ projects across civic tech, data journalism, open-source platforms and interactive installations for public and private clients.</div>
</div>
<div class="experience-item">
<div class="exp-header">Moedax Digital Services</div>
<div class="exp-meta">Founder & CTO · Lisbon · Rio de Janeiro · 2018 – 2021</div>
<div class="exp-desc">Fintech startup connecting CBDC digital currency with KYC compliance automation; built data pipelines and banking integrations in Python.</div>
</div>
<div class="experience-item">
<div class="exp-header">GFOSS.eu / Code + Create</div>
<div class="exp-meta">Web Programming Teacher · Athens, Greece · 2017 – 2018</div>
<div class="exp-desc">Taught web programming (HTML, CSS, jQuery) to refugee and local youth through the EU-funded Code + Create initiative.</div>
</div>
<div class="experience-item">
<div class="exp-header">Tactical Tech Collective</div>
<div class="exp-meta">Full-Stack Web Architect · Berlin, Germany · Dec 2014 – Jun 2016</div>
<div class="exp-desc">Built investigative data tools and platforms under the Exposing the Invisible team (Ruby on Rails, data visualisation).</div>
</div>
<div class="experience-item">
<div class="exp-header">Trommsdorff + Drüner</div>
<div class="exp-meta">Full-Stack Engineer · Berlin, Germany</div>
<div class="exp-desc">Innovation team — Business Intelligence dashboards for marketing consultancy clients.</div>
</div>
<div class="experience-item">
<div class="exp-header">Cortex Intelligence</div>
<div class="exp-meta">Developer · Rio de Janeiro, Brazil</div>
<div class="exp-desc">Competitive Intelligence and Data Mining R&D team.</div>
</div>
</div>
<div class="section">
<h1>E D U C A T I O N</h1>
<div class="key-value"><span class="key">Postgraduate in Data Science for Finance</span><span class="value">NOVA IMS Information Management School, Lisbon — 2021</span></div>
<div class="key-value"><span class="key">Master in Information Systems</span><span class="value">PPGI/UNIRIO — Knowledge Representation & Reasoning — 2010–2012</span></div>
<div class="key-value"><span class="key">Bachelor in Computer Science</span><span class="value">Metodista Bennett, Rio de Janeiro — 2004–2009</span></div>
</div>
<div class="section">
<h1>L A N G U A G E S</h1>
<div class="key-value"><span class="key">Portuguese</span><span class="value">native</span></div>
<div class="key-value"><span class="key">English</span><span class="value">full professional</span></div>
<div class="key-value"><span class="key">Spanish</span><span class="value">full professional</span></div>
<div class="key-value"><span class="key">German</span><span class="value">B1 — TELC certified · 3 yrs Berlin + 3 yrs Basel</span></div>
</div>
<div class="section">
<h1>C E R T I F I C A T I O N S</h1>
<ul>
<li>Swiss Federal Act on Data Protection (nFADP)</li>
<li>Gen AI Foundational Models — NLP & LLMs</li>
<li>AI Agents using RAG and LangChain</li>
</ul>
</div>
<div class="section">
<h1>T E C H S K I L L S</h1>
<div class="key-value"><span class="key">Languages & Frameworks</span><span class="value">Python · Ruby on Rails · TypeScript · React · Java</span></div>
<div class="key-value"><span class="key">DevOps & Infra</span><span class="value">Docker · Kubernetes · CI/CD · AWS · Linux · Git</span></div>
<div class="key-value"><span class="key">Data & AI</span><span class="value">SQL · ETL · Data Engineering · RAG · LangChain · LLM integrations · Data Science</span></div>
<div class="key-value"><span class="key">Architecture</span><span class="value">REST APIs · MVC · OOP · UML · System Design · Web Crawling & Scraping</span></div>
</div>
<div class="small">
References available upon request · CV updated May 2026
</div>
</body>
</html>
-243
View File
@@ -1,243 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Rafael Polo - CV</title>
<style>
@page {
size: 8.2681in 11.6929in;
margin: 0.5in;
}
body {
font-family: Liberation Sans, Carlito, Calibri, Georgia, sans-serif;
font-size: 11pt;
line-height: 1.3;
margin: 0;
padding: 0;
}
.container {
display: table;
width: 100%;
}
.left-col {
display: table-cell;
width: 65%;
padding-right: 0.2in;
vertical-align: top;
}
.right-col {
display: table-cell;
width: 35%;
vertical-align: top;
text-align: right;
}
.photo {
width: 2in;
height: auto;
border: 1px solid #ccc;
}
.title {
font-size: 24pt;
font-weight: bold;
margin-bottom: 0.05in;
}
.subtitle {
font-size: 12pt;
font-style: italic;
margin-bottom: 0.2in;
color: #444;
}
h3 {
font-size: 12pt;
font-weight: bold;
margin: 0.15in 0 0.08in 0;
text-transform: uppercase;
letter-spacing: 0.05in;
border-bottom: 1px solid #999;
padding-bottom: 0.03in;
}
.personal-table {
width: 100%;
border-collapse: collapse;
}
.personal-table td {
padding: 0.02in 0;
vertical-align: top;
}
.personal-table .label {
font-weight: bold;
width: 1.2in;
color: #333;
}
.personal-table .header {
font-weight: bold;
font-size: 12pt;
text-transform: uppercase;
letter-spacing: 0.05in;
padding-bottom: 0.05in;
}
.section-header {
font-weight: bold;
font-size: 11pt;
text-transform: uppercase;
letter-spacing: 0.03in;
margin-top: 0.15in;
color: #333;
}
ul {
margin: 0.05in 0;
padding-left: 0.15in;
}
li {
margin-bottom: 0.04in;
font-size: 10pt;
}
.job-title {
font-weight: bold;
}
.job-meta {
font-style: italic;
font-size: 10pt;
}
.job-company {
font-weight: bold;
}
.job-desc {
font-style: italic;
font-size: 10pt;
margin-left: 0.1in;
}
.edu-item {
font-size: 10pt;
margin-bottom: 0.03in;
}
.edu-school {
font-style: italic;
}
.skill-category {
font-weight: bold;
font-size: 10pt;
margin-top: 0.05in;
}
.skill-list {
font-size: 10pt;
margin-left: 0.1in;
}
.footer {
font-size: 9pt;
color: #666;
margin-top: 0.3in;
border-top: 1px solid #ccc;
padding-top: 0.1in;
}
</style>
</head>
<body>
<div class="container">
<div class="left-col">
<p class="title">Rafael Polo</p>
<p class="subtitle">Senior Software Engineer — Platform, Data & AI</p>
<table class="personal-table">
<tr>
<td class="header" colspan="2">Personal</td>
</tr>
<tr>
<td class="label">Address:</td>
<td>Basel, 4055, Switzerland</td>
</tr>
<tr>
<td class="label">Email:</td>
<td>rafael@extrapolo.com</td>
</tr>
<tr>
<td class="label">LinkedIn:</td>
<td>linkedin.com/in/rafaelpolo</td>
</tr>
<tr>
<td class="label">Web:</td>
<td>extrapolo.com</td>
</tr>
<tr>
<td class="label">Citizenship:</td>
<td>Portuguese (EU) · Brazilian — no work permit required</td>
</tr>
<tr>
<td class="label">Languages:</td>
<td>Fluent English · German B1 TELC (3 yrs Berlin + 3 yrs Basel) · EU citizen, immediately available</td>
</tr>
</table>
<h3>Formal Education</h3>
<ul>
<li><em><strong>Postgraduate in Data Science for Finance</strong></em> – 2021<br>
<span class="edu-school">NOVA IMS Information Management School, Lisbon</span></li>
<li><em><strong>Master in Information Systems</strong></em> – 2010–2012<br>
<span class="edu-school">Research Area: Knowledge Representation & Reasoning, PPGI/UNIRIO</span></li>
<li><em><strong>Bachelor in Computer Science</strong></em> – 2004–2009<br>
<span class="edu-school">Metodista Bennett, Rio de Janeiro</span></li>
<li>Thesis: Agile Systems Development for Web 2.0 with Ruby on Rails</li>
</ul>
<h3>Relevant Professional Experience</h3>
<ul>
<li><strong>Swisscom</strong> – <em>2024–2025</em> – <em>Zürich, Switzerland</em>
<p class="job-desc"><strong>DevOps Engineer</strong> developing platforms for Telecommunication Operations.</p></li>
<li><strong>EDGE Empower®</strong> – <em>2024–2025</em> – <em>Baar, Switzerland</em>
<p class="job-desc"><strong>Senior Technical Lead</strong> managing projects and external UX & Dev Teams for a SaaS Company.</p></li>
<li><strong>ExtraPolo — Independent Consulting</strong> – <em>2010–2022</em> – <em>Rio de Janeiro · Berlin · Athens · Lisbon</em>
<p class="job-desc">For more than 10 years, worked as an independent Software Developer and IT Consultant, developing dozens of Projects for public and private contractors in Brazil, Germany, Greece and Switzerland.</p></li>
<li><strong>Moedax Digital Services</strong> – <em>2018–2021</em> – <em>Lisbon and Rio de Janeiro</em>
<p class="job-desc"><strong>Founder & CTO</strong> – connected Brazilian CBDC with KYC processes and automation</p></li>
<li><strong>GFOSS.eu / Code + Create</strong> – <em>2017–2018</em> – <em>Athens, Greece</em>
<p class="job-desc"><strong>Web Programming Teacher</strong> – taught web programming to refugee and local youth</p></li>
<li><strong>Tactical Tech Collective</strong> – <em>2014–2016</em> – <em>Berlin, Germany</em>
<p class="job-desc"><strong>Full-Stack Web Architect</strong> on an NGO under the Exposing the Invisible Team.</p></li>
<li><strong>Trommsdorf + Drüner</strong> – <em>2013–2014</em> – <em>Berlin, Germany</em>
<p class="job-desc"><strong>Full-stack Engineer</strong> – Innovation Team developing Business Intelligence dashboards.</p></li>
<li><strong>Cortex Intelligence</strong> – <em>2007–2008</em> – <em>Rio de Janeiro, Brazil</em>
<p class="job-desc"><strong>Developer</strong> in the Competitive Intelligence and Data Mining Team.</p></li>
</ul>
<h3>Certifications</h3>
<ul>
<li>Swiss Federal Act on Data Protection (nFADP)</li>
<li>Gen AI Foundational Models — NLP & LLMs</li>
<li>AI Agents using RAG and LangChain</li>
</ul>
<h3>Relevant Tech Skills</h3>
<ul>
<li>System Analysis & Modeling with UML</li>
<li>Quick Proof-of-Concepts development, deploy and management.</li>
<li>Large Language Models, Gen AI, LangChain integration and Processes Automation</li>
<li>MVC System Architecture, Design Patterns & Object-Oriented Programming</li>
<li>Data Engineering, Data Science, Relational Databases & SQL</li>
<li>Experience with Blockchain, Smart Contracts and P2P systems</li>
<li>Distributing and Scaling Processes with Message Queues</li>
<li>Developing Web Crawlers & Bots for Data Mining & ETL</li>
<li>Linux Systems, VPS, DevOps, SSH & Deploy with Continuous Integration processes</li>
<li>Projects mostly developed in Python, Ruby on Rails, Django, Java</li>
<li>Full Stack Developer & Front-end Web Design with HTML, CSS and JavaScript frameworks</li>
<li>CI/CD, Docker, Kubernetes and GitHub workflows</li>
</ul>
<h3>Natural Languages</h3>
<ul>
<li>Native Brazilian Portuguese</li>
<li>Advanced Spoken Spanish</li>
<li>A2 level Greek – <em>3 years in Athens</em></li>
<li>B1 level German / TELC proof – <em>3 years in Berlin</em> and 3 in Switzerland</li>
<li>Fluent English – <em>13 years in between international teams</em></li>
</ul>
<div class="footer">
References available upon request · CV updated May 2026
</div>
</div>
<div class="right-col">
<!-- Photo placeholder - remove if not needed -->
</div>
</div>
</body>
</html>
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
-130
View File
@@ -1,130 +0,0 @@
Rafael Polo
Basel, 4055, Switzerland
rafael@extrapolo.com
linkedin.com/in/rafaelpolo
extrapolo.com
Senior Software Engineer — Platform, Data & AI
Swiss B permit · Portuguese (EU) citizen
20+ years building production systems across Switzerland, Germany, Greece and Brazil. Specialised in platform
engineering, data pipelines and AI/LLM integrations. Fluent English · German B1 TELC (3 yrs Berlin + 3 yrs Basel) · EU
citizen, immediately available.
P R O F E S S I O N A L E X P E R I E N C E
Swisscom
DevOps Engineer · Zürich, Switzerland
Modernization of mission-critical internal platforms & CI/CD pipelines for high-availability Telecom infrastructure.
EDGE Empower®
Senior Technical Lead · Baar, Switzerland
Mar 2024 – Mar 2025
Feb 2023 – Feb 2024
Built a PayTool cutting processing time by 98%; reduced CI/CD pipeline from 14 → 4 minutes; managed 3 developers and a UX
designer for a SaaS product.
ExtraPolo — Independent Consulting
Software Engineer & Consultant · Rio de Janeiro · Berlin · Athens · Lisbon
2010 – 2022
40+ projects across civic tech, data journalism, open-source platforms and interactive installations for public and private clients. Includes Rodado (~730 Brazilian public datasets, 1TB Parquet, DuckDB, NL-to-SQL over MCP) and HelvetiScan (scanner/mapper of 2.5M+ Swiss .ch domains — HTTP, DNS, TLS, WHOIS, CVE).
Moedax Digital Services
Founder & CTO · Lisbon · Rio de Janeiro
2018 – 2021
Fintech startup connecting CBDC digital currency with KYC compliance automation; built data pipelines and banking integrations in
Python.
GFOSS.eu / Code + Create
Web Programming Teacher · Athens, Greece
2017 – 2018
Taught web programming (HTML, CSS, jQuery) to refugee and local youth through the EU-funded Code + Create initiative.
Tactical Tech Collective
Full-Stack Web Architect · Berlin, Germany
Dec 2014 – Jun 2016
Built investigative data tools and platforms under the Exposing the Invisible team (Ruby on Rails, data visualisation).
Trommsdorff + Drüner
Full-Stack Engineer · Berlin, Germany
Innovation team — Business Intelligence dashboards for marketing consultancy clients.
Cortex Intelligence
Developer · Rio de Janeiro, Brazil
Competitive Intelligence and Data Mining R&D team.
E D U C A T I O N
L A N G U A G E S
Dec 2013 – Jan 2014
2008 – 2010
Postgraduate in Data Science for Finance
NOVA IMS Information Management School, Lisbon — 2021
Master in Information Systems
PPGI/UNIRIO — Knowledge Representation & Reasoning —
2010–2012
Bachelor in Computer Science
Metodista Bennett, Rio de Janeiro — 2004–2009
Portuguese — native
English — full professional
Spanish — full professional
German B1 — TELC certified · 3 yrs Berlin + 3 yrs Basel
C E R T I F I C A T I O N S
Swiss Federal Act on Data Protection (nFADP)
Gen AI Foundational Models — NLP & LLMs
AI Agents using RAG and LangChain
T E C H S K I L L S
Languages & Frameworks · Python · Ruby on Rails ·
TypeScript · React
DevOps & Infra · Docker · Kubernetes · CI/CD · AWS · Linux ·
Git
Data & AI · SQL · ETL · Data Engineering · RAG · LangChain ·
LLM integrations · Data Science
Architecture · REST APIs · MVC · OOP · UML · System Design ·
Web Crawling & Scraping
References available upon request  ·  CV updated May 2026
+177
View File
@@ -0,0 +1,177 @@
// Daily watch for the "Delivery Lead – Agentic Solutions" opening (Biomedical
// Research Digital & Data, likely Novartis) that MRP-Global posted on LinkedIn
// as job 4473851998 on 2026-10-03. Looks for the same role resurfacing in
// another form — another agency, a direct Novartis posting, a retitled
// repost — and reports when the original stops accepting applications.
//
// Runs from launchd (com.rafapolo.linkme-watch-delivery-lead, daily 10:00).
// Pushes to Telegram only when something new turns up; everything else goes to
// results/watch-delivery-lead.log. State lives in results/.watch-delivery-lead.json,
// so a hit is reported once. `--dry-run` prints instead of sending.
import { fetchDescription } from "../fetch.ts";
import { send, escapeHtml } from "../telegram.ts";
const ORIGINAL_ID = "4473851998";
const STATE_FILE = "results/.watch-delivery-lead.json";
const DRY_RUN = process.argv.includes("--dry-run");
const UA =
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36";
// Searches cast wide; SIGNATURE decides. A repost of this opening reuses the
// client's wording, so a candidate needs one client-specific phrase (STRONG)
// plus one role phrase. "agentic" + "delivery lead" alone matched Eraneos and
// AWS on the first dry run (2026-10-05) — generic consultancy wording.
const LINKEDIN_QUERIES = [
"delivery lead agentic",
"delivery lead AI data pharma",
"delivery lead biomedical",
"agentic solutions delivery",
"biomedical research digital data",
"delivery manager agentic",
];
const NOVARTIS_QUERIES = ["delivery lead", "delivery manager", "agentic", "biomedical research digital"];
const SIGNATURE: [string, RegExp][] = [
["agentic", /\bagentic\b/i],
["Biomedical Research", /biomedical\s+research/i],
["Digital & Data", /digital\s*(?:&|and)\s*data/i],
["delivery lead", /delivery\s+lead/i],
["Palantir", /\bpalantir\b/i],
["Databricks", /\bdatabricks\b/i],
["RWD", /\bRWD\b|real[-\s]world\s+data|clinical\s+trials?/i],
];
const STRONG = new Set(["Biomedical Research", "Digital & Data", "Palantir", "RWD"]);
const ROLE = new Set(["agentic", "delivery lead"]);
const isMatch = (m: string[]) => m.some((x) => STRONG.has(x)) && m.some((x) => ROLE.has(x));
const TITLE_RE = /deliver|agentic|programme?\s+lead|project\s+lead/i;
interface Hit { key: string; title: string; company: string; link: string; matched: string[] }
interface State { seen: string[]; reported: string[]; originalClosed?: boolean }
async function loadState(): Promise<State> {
const f = Bun.file(STATE_FILE);
return (await f.exists()) ? await f.json() : { seen: [], reported: [] };
}
function signature(text: string): string[] {
return SIGNATURE.filter(([, re]) => re.test(text)).map(([name]) => name);
}
const strip = (s: string) =>
s.replace(/<[^>]+>/g, " ").replace(/&amp;/g, "&").replace(/&#39;|&#x27;/g, "'").replace(/\s+/g, " ").trim();
async function get(url: string): Promise<string> {
const res = await fetch(url, { headers: { "User-Agent": UA } });
if (!res.ok) throw new Error(`${res.status} ${url}`);
return res.text();
}
async function searchLinkedIn(state: State): Promise<Hit[]> {
const cards = new Map<string, { title: string; company: string }>();
for (const q of LINKEDIN_QUERIES) {
// Past month, Switzerland-wide. One page is enough: these queries are narrow.
const url = `https://www.linkedin.com/jobs-guest/jobs/api/seeMoreJobPostings/search?keywords=${encodeURIComponent(q)}&location=Switzerland&f_TPR=r2592000&start=0`;
try {
const html = await get(url);
for (const c of html.split("<li>").slice(1)) {
const id = c.match(/jobs\/view\/[^"]*?(\d{8,})/)?.[1];
const title = strip(c.match(/base-search-card__title[^>]*>([\s\S]*?)<\/h3>/)?.[1] ?? "");
const company = strip(c.match(/base-search-card__subtitle[^>]*>([\s\S]*?)<\/h4>/)?.[1] ?? "");
if (id && id !== ORIGINAL_ID && TITLE_RE.test(title)) cards.set(id, { title, company });
}
} catch (e) {
console.log(` linkedin "${q}": ${e}`);
}
await Bun.sleep(1500);
}
const hits: Hit[] = [];
for (const [id, { title, company }] of cards) {
const key = `li-${id}`;
if (state.seen.includes(key)) continue;
const desc = await fetchDescription(id);
if (desc === null) continue; // unreadable — retry tomorrow rather than mark seen
state.seen.push(key);
const matched = signature(`${title} ${desc}`);
console.log(` li ${id} ${title} @ ${company}: [${matched.join(", ")}]`);
if (isMatch(matched)) {
hits.push({ key, title, company, link: `https://www.linkedin.com/jobs/view/${id}/`, matched });
}
}
return hits;
}
async function searchNovartis(state: State): Promise<Hit[]> {
const found = new Map<string, { title: string; path: string }>();
for (const q of NOVARTIS_QUERIES) {
const url = `https://www.novartis.com/careers/career-search?search_api_fulltext=${encodeURIComponent(q)}&country%5B%5D=LOC_CH`;
try {
const html = await get(url);
for (const m of html.matchAll(/href="(\/careers\/career-search\/job\/details\/(req-\d+)[^"]*)"[^>]*>([\s\S]*?)<\/a>/g)) {
const title = strip(m[3]);
if (TITLE_RE.test(title)) found.set(m[2], { title, path: m[1] });
}
} catch (e) {
console.log(` novartis "${q}": ${e}`);
}
}
const hits: Hit[] = [];
for (const [req, { title, path }] of found) {
const key = `nv-${req}`;
if (state.seen.includes(key)) continue;
const link = `https://www.novartis.com${path}`;
let desc: string;
try {
desc = strip(await get(link));
} catch {
continue;
}
state.seen.push(key);
const matched = signature(`${title} ${desc}`);
console.log(` nv ${req} ${title}: [${matched.join(", ")}]`);
if (isMatch(matched)) hits.push({ key, title, company: "Novartis", link, matched });
}
return hits;
}
async function originalClosed(): Promise<boolean | null> {
try {
const html = await get(`https://www.linkedin.com/jobs/view/${ORIGINAL_ID}/`);
return /no longer accepting applications/i.test(html);
} catch {
return null;
}
}
const state = await loadState();
console.log(`[${new Date().toISOString()}] watch-delivery-lead`);
const hits = [...(await searchLinkedIn(state)), ...(await searchNovartis(state))].filter(
(h) => !state.reported.includes(h.key),
);
const closed = await originalClosed();
const lines: string[] = [];
for (const h of hits) {
lines.push(
`• <b>${escapeHtml(h.title)}</b> — ${escapeHtml(h.company)}\n ${h.link}\n matched: ${escapeHtml(h.matched.join(", "))}`,
);
}
if (closed === true && !state.originalClosed) {
lines.push(`• The original MRP-Global posting (${ORIGINAL_ID}) is no longer accepting applications.`);
}
if (lines.length) {
const msg = `🔎 <b>Delivery Lead – Agentic Solutions watch</b>\n\n${lines.join("\n\n")}`;
if (DRY_RUN) console.log(msg);
else await send(msg);
}
// Only mark as reported after a successful send, same rule as daily.ts.
state.reported.push(...hits.map((h) => h.key));
if (closed === true) state.originalClosed = true;
if (!DRY_RUN) await Bun.write(STATE_FILE, JSON.stringify(state, null, 2));
console.log(` ${hits.length} new hit(s), original closed: ${closed}`);