Auto-deploy: 2026-08-05 16:58:10
This commit is contained in:
@@ -106,10 +106,15 @@
|
||||
<h2>Professional Experience</h2>
|
||||
{{EXPERIENCE_BLOCK}}
|
||||
|
||||
<h2>Open Source</h2>
|
||||
{{OPENSOURCE_BLOCK}}
|
||||
|
||||
<!-- Certifications sit inside Education rather than claiming a heading of
|
||||
their own: they are data-analytics certificates on a mobile engineering
|
||||
CV, so a dedicated section would draw the eye to the least relevant
|
||||
content on the page. -->
|
||||
<h2>Education</h2>
|
||||
{{EDUCATION_BLOCK}}
|
||||
|
||||
<h2>Certifications</h2>
|
||||
{{CERTIFICATIONS_BLOCK}}
|
||||
|
||||
<h2>Additional Information</h2>
|
||||
|
||||
+44
-5
@@ -199,9 +199,23 @@ Return ONLY raw JSON (no markdown fences) with EXACTLY these keys:
|
||||
],
|
||||
"ats_keywords_matched": ["exact terms from the posting that now appear in the CV"],
|
||||
"ats_keywords_missing": ["requirements from the posting I genuinely cannot claim"],
|
||||
"estimated_ats_score": 0
|
||||
"estimated_ats_score": 0,
|
||||
"is_founding_or_startup_role": false
|
||||
}
|
||||
|
||||
"is_founding_or_startup_role": true ONLY when the hiring company is an early-stage
|
||||
startup, or the posting explicitly seeks a founding engineer / first engineer /
|
||||
0-to-1 builder / someone to own a product end-to-end. false for established
|
||||
companies, enterprises, banks, agencies and government. This controls whether my
|
||||
CV presents a past role as "Founding Mobile Architect" or "Lead Mobile Engineer" —
|
||||
identical work, framed for the reader.
|
||||
|
||||
CONSISTENCY RULE: when "is_founding_or_startup_role" is false, the words
|
||||
"Founding" and "Founder" must NOT appear anywhere in "headline" or "summary"
|
||||
either. Describe the same 0-to-1 ownership as "built and launched from zero" or
|
||||
"owned end-to-end" instead. A CV that avoids "Founding" in the job title but
|
||||
keeps it in the summary reads as careless.
|
||||
|
||||
RULES FOR "roles":
|
||||
- Include EVERY role index that exists in MY REAL DATA, in the same order.
|
||||
- For each role select the 3-4 bullets MOST relevant to this job (fewer for the
|
||||
@@ -283,9 +297,15 @@ PROMPT;
|
||||
$contactBlock =
|
||||
'<div>' . e($id['location']) . ' | ' . e($id['phone'])
|
||||
. ' | ' . e($id['email']) . '</div>'
|
||||
. '<div>' . e($id['linkedin']) . ' | ' . e($id['portfolio'])
|
||||
. '<div>' . e($id['linkedin']) . ' | ' . e($id['github'])
|
||||
. ' | ' . e($id['portfolio'])
|
||||
. ' | ' . e($id['productSite']) . '</div>';
|
||||
|
||||
// "Founding" reads as an asset at a startup and as flight risk at an
|
||||
// established company. The model classifies the employer; the facts under
|
||||
// the title are identical either way.
|
||||
$isFoundingContext = $integrityClean && !empty($ai['is_founding_or_startup_role']);
|
||||
|
||||
$skillsBlock = '';
|
||||
foreach ($profile['skills'] as $group => $items) {
|
||||
$skillsBlock .= '<p class="skill-line"><span class="label">' . e($group) . ':</span> '
|
||||
@@ -305,7 +325,17 @@ PROMPT;
|
||||
$edu = $profile['education'];
|
||||
$educationBlock = '<p>' . e($edu['degree']) . ' — ' . e($edu['institution']) . '. ' . e($edu['note']) . '</p>';
|
||||
|
||||
$certBlock = '<p>' . e(implode(' · ', $profile['certifications'])) . '</p>';
|
||||
$certBlock = '<p class="skill-line"><span class="label">Certifications:</span> '
|
||||
. e(implode(' · ', $profile['certifications'])) . '</p>';
|
||||
|
||||
// Package URLs are printed as plain text, not anchor labels — many parsers
|
||||
// read the visible text rather than the href, and a recruiter needs to be
|
||||
// able to retype these.
|
||||
$openSourceBlock = '';
|
||||
foreach (($profile['openSource'] ?? []) as $pkg) {
|
||||
$openSourceBlock .= '<p class="skill-line"><span class="label">' . e($pkg['name']) . '</span> — '
|
||||
. e($pkg['platform']) . ' · ' . e($pkg['url']) . '. ' . e($pkg['description']) . '</p>';
|
||||
}
|
||||
|
||||
$availability = $market === 'amman'
|
||||
? 'Based in Amman, Jordan. Available immediately for on-site, hybrid and remote roles.'
|
||||
@@ -329,7 +359,8 @@ PROMPT;
|
||||
|
||||
$buildHtml = function (array $d) use (
|
||||
$profile, $id, $template, $aiRoles, $headline, $summary, $coreSkills,
|
||||
$contactBlock, $skillsBlock, $educationBlock, $certBlock, $availability
|
||||
$contactBlock, $skillsBlock, $educationBlock, $certBlock, $availability,
|
||||
$openSourceBlock, $isFoundingContext
|
||||
) {
|
||||
// Headline metrics collapse to a single dense line. As four separate
|
||||
// bullets they cost four lines to say what one line says.
|
||||
@@ -351,8 +382,15 @@ PROMPT;
|
||||
|
||||
$experienceBlock = '';
|
||||
foreach ($profile['experience'] as $ri => $role) {
|
||||
$roleTitle = $role['title'];
|
||||
if (!empty($role['titleVariants'])) {
|
||||
$roleTitle = $isFoundingContext
|
||||
? ($role['titleVariants']['founding'] ?? $roleTitle)
|
||||
: ($role['titleVariants']['standard'] ?? $roleTitle);
|
||||
}
|
||||
|
||||
$experienceBlock .= '<div class="job">';
|
||||
$experienceBlock .= '<p class="job-title">' . e($role['title']) . '</p>';
|
||||
$experienceBlock .= '<p class="job-title">' . e($roleTitle) . '</p>';
|
||||
$experienceBlock .= '<p class="job-company">' . e($role['company']) . ' — ' . e($role['location']) . '</p>';
|
||||
$experienceBlock .= '<p class="job-dates">' . e($role['start']) . ' – ' . e($role['end']) . '</p>';
|
||||
|
||||
@@ -394,6 +432,7 @@ PROMPT;
|
||||
'{{DYNAMIC_SKILLS}}' => e($coreSkills),
|
||||
'{{SKILLS_BLOCK}}' => $skillsBlock,
|
||||
'{{EXPERIENCE_BLOCK}}' => $experienceBlock,
|
||||
'{{OPENSOURCE_BLOCK}}' => $openSourceBlock,
|
||||
'{{EDUCATION_BLOCK}}' => $educationBlock,
|
||||
'{{CERTIFICATIONS_BLOCK}}' => $certBlock,
|
||||
'{{LANGUAGES}}' => e($id['languages']),
|
||||
|
||||
+37
-18
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user