fix: split skip counters for accurate reporting, complete status docs

- Split skipped_no_easy_apply into skipped_no_apply (no button/modal)
  and skipped_other (honeypot/stuck/incomplete) for clearer reporting
- Update Telegram summary, status.mjs display, and job_applier counters
- Add missing skipped_easy_apply_unsupported to README status table

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-05 17:44:25 -08:00
parent 8212f97aba
commit 1c3e9f3561
4 changed files with 20 additions and 7 deletions

View File

@@ -202,6 +202,7 @@ claw-apply/
| `skipped_honeypot` | Honeypot question detected |
| `skipped_recruiter_only` | LinkedIn recruiter-only listing |
| `skipped_external_unsupported` | External ATS (Greenhouse, Lever, etc. — stubs ready) |
| `skipped_easy_apply_unsupported` | LinkedIn job without Easy Apply button |
| `skipped_no_apply` | No apply button, modal, or submit found on page |
| `stuck` | Modal progress stalled |
| `incomplete` | Ran out of modal steps without submitting |

View File

@@ -40,7 +40,7 @@ async function main() {
const startedAt = Date.now();
const results = {
submitted: 0, failed: 0, needs_answer: 0, total: 0,
skipped_recruiter: 0, skipped_external: 0, skipped_no_easy_apply: 0,
skipped_recruiter: 0, skipped_external: 0, skipped_no_apply: 0, skipped_other: 0,
already_applied: 0, atsCounts: {}
};
@@ -201,13 +201,19 @@ async function handleResult(job, result, results, settings) {
case 'skipped_no_apply':
case 'skipped_easy_apply_unsupported':
console.log(` ⏭️ Skipped — ${status}`);
updateJobStatus(job.id, status, { title, company });
appendLog({ ...job, title, company, status });
results.skipped_no_apply++;
break;
case 'skipped_honeypot':
case 'stuck':
case 'incomplete':
console.log(` ⏭️ Skipped — ${status}`);
updateJobStatus(job.id, status, { title, company });
appendLog({ ...job, title, company, status });
results.skipped_no_easy_apply++;
results.skipped_other++;
break;
default:

View File

@@ -47,20 +47,24 @@ export function formatSearchSummary(added, skipped, platforms) {
export function formatApplySummary(results) {
const { submitted, failed, needs_answer, total,
skipped_recruiter, skipped_external, skipped_no_easy_apply,
already_applied, atsCounts } = results;
skipped_recruiter, skipped_external, skipped_no_apply,
skipped_other, already_applied, atsCounts } = results;
const lines = [
`✅ *Apply Run Complete* — ${total} jobs processed`,
``,
`📬 Applied: ${submitted}`,
`⏭️ Skipped (no Easy Apply): ${skipped_no_easy_apply}`,
`⏭️ No apply button: ${skipped_no_apply || 0}`,
`🚫 Recruiter-only: ${skipped_recruiter}`,
`🔁 Already applied: ${already_applied || 0}`,
`❌ Failed: ${failed}`,
`💬 Needs your answer: ${needs_answer}`,
];
if (skipped_other > 0) {
lines.push(`⚠️ Other skips (honeypot/stuck/incomplete): ${skipped_other}`);
}
if (skipped_external > 0 && atsCounts) {
const sorted = Object.entries(atsCounts).sort((a, b) => b[1] - a[1]);
lines.push(``, `🌐 *External ATS — ${skipped_external} jobs* (saved for later):`);

View File

@@ -80,7 +80,8 @@ function buildStatus() {
needs_answer: byStatus['needs_answer'] || 0,
skipped_external: byStatus['skipped_external_unsupported'] || 0,
skipped_recruiter: byStatus['skipped_recruiter_only'] || 0,
skipped_no_easy_apply: byStatus['skipped_easy_apply_unsupported'] || 0,
skipped_no_apply: (byStatus['skipped_easy_apply_unsupported'] || 0) + (byStatus['skipped_no_apply'] || 0),
skipped_other: (byStatus['skipped_honeypot'] || 0) + (byStatus['stuck'] || 0) + (byStatus['incomplete'] || 0),
already_applied: byStatus['already_applied'] || 0,
by_platform: byPlatform,
},
@@ -159,7 +160,8 @@ function formatReport(s) {
` 💬 Needs your answer: ${q.needs_answer}`,
` ❌ Failed: ${q.failed}`,
` 🚫 Recruiter-only: ${q.skipped_recruiter}`,
` ⏭️ No Easy Apply: ${q.skipped_no_easy_apply}`,
` ⏭️ No apply button: ${q.skipped_no_apply}`,
` ⚠️ Other skips: ${q.skipped_other || 0}`,
` 🌐 External ATS: ${q.skipped_external}`,
);