Auto-deploy: 2026-08-05 17:08:23

This commit is contained in:
Hamza-Ayed
2026-08-05 17:08:23 +03:00
parent 27801cb496
commit 772d843817
3 changed files with 44 additions and 13 deletions
+6 -2
View File
@@ -167,8 +167,12 @@ const PROFILE_DATA = {
bullets: [
{ text: 'Delivered 30+ production-grade mobile applications across e-commerce, delivery, healthcare and news sectors, acting as technical decision-maker for early-stage clients.', tags: ['delivery', 'leadership', 'mobile', 'scale'] },
{ text: 'Migrated legacy Android (Java) applications to Flutter, cutting maintenance complexity and delivery timelines by roughly 50%.', tags: ['flutter', 'migration', 'mobile'] },
{ text: 'Built custom Flutter plugins and tailored API layers to integrate with complex legacy backend systems.', tags: ['flutter', 'integration', 'architecture'] },
{ text: 'Owned App Store and Google Play release management end-to-end, from store listings and review submission through versioned production rollout.', tags: ['mobile', 'release', 'ios', 'android', 'delivery'] }
// Ordered by how often each is actually screened for in mobile roles.
// When the tailoring model returns fewer bullets than the page allows,
// the generator tops up in this order — so the more commonly required
// evidence fills the slot first.
{ text: 'Owned App Store and Google Play release management end-to-end, from store listings and review submission through versioned production rollout.', tags: ['mobile', 'release', 'ios', 'android', 'delivery'] },
{ text: 'Built custom Flutter plugins and tailored API layers to integrate with complex legacy backend systems.', tags: ['flutter', 'integration', 'architecture'] }
]
}
],
+28 -1
View File
@@ -401,7 +401,8 @@ PROMPT;
if ($b !== '') $bullets[] = $b;
}
}
if (empty($bullets)) {
$fromAi = !empty($bullets);
if (!$fromAi) {
foreach ($role['bullets'] as $b) {
$bullets[] = $b['text'];
}
@@ -413,6 +414,32 @@ PROMPT;
$cap = $d['caps'][$ri] ?? 2;
$bullets = array_slice($bullets, 0, $cap);
// The model also errs the other way, returning fewer bullets than
// the layout has room for. An empty slot is wasted page space, and
// worse, it can strand a skill in the Technical Skills line with no
// supporting evidence anywhere in the experience. Top up from the
// master bullets the model did not pick, keeping its ordering first.
// Which master bullets did the model already use? Match on the
// "roleIndex.bulletIndex" ids it returns, not on the text: it
// rewrites wording to carry the job's keywords, so comparing strings
// would treat a rewritten bullet as a new one and print the same
// fact twice. Without usable ids we cannot tell what was used, so we
// leave the role as-is rather than risk a duplicate.
$usedIdx = [];
foreach (($aiRoles[$ri]['bullet_ids'] ?? []) as $bid) {
$parts = explode('.', (string)$bid);
if (count($parts) === 2) $usedIdx[] = (int)$parts[1];
}
if ($fromAi && $usedIdx && count($bullets) < $cap) {
foreach ($role['bullets'] as $bi => $master) {
if (count($bullets) >= $cap) break;
if (!in_array($bi, $usedIdx, true)) {
$bullets[] = $master['text'];
}
}
}
$experienceBlock .= '<ul>';
foreach ($bullets as $b) {
$experienceBlock .= '<li>' . e($b) . '</li>';
+10 -10
View File
File diff suppressed because one or more lines are too long