# How Career-Ops Assesses Job Posting Legitimacy: The Block-G Gate System

> Career-Ops assesses job posting legitimacy using the Block-G gate system. Learn how it verifies live, non-blacklisted, and budget-compliant listings to prevent processing expired or suspicious offers.

- Repository: [Santiago Fernández de Valderrama/career-ops](https://github.com/santifer/career-ops)
- Tags: deep-dive
- Published: 2026-08-28

---

**Career-Ops evaluates job posting legitimacy through a dedicated Block G stage in its A-G pipeline, employing a liveness gate, blacklist verification, and a bounded research budget to halt processing of expired or suspicious listings before substantive scoring begins.**

Career-Ops, an open-source job application automation toolkit maintained at `santifer/career-ops`, treats posting legitimacy as a critical prerequisite to candidate evaluation. The system implements a multi-layered filtering mechanism—formally designated as **Block G** within its evaluation pipeline—to prevent users from wasting time on dead URLs, blacklist employers, or potentially fraudulent opportunities. Understanding how Career-Ops assesses job posting legitimacy helps users interpret the "High Confidence," "Proceed with Caution," and "Suspicious" tiers that appear in every report header.

## The Three Gates That Precede Legitimacy Scoring

Before Career-Ops calculates substantive match scores (Blocks A-F), it runs three protective gates designed to catch obvious disqualifiers early and conserve resources.

### The Liveness Gate

The first checkpoint verifies whether a job posting is still active. Implemented in `check-liveness.mjs`, this gate performs a cost-effective ATS API check, then falls back to Playwright browser automation to inspect page titles, URLs, and visible content. The system classifies postings as *active*, *expired*, or *uncertain*.

If the liveness check returns *expired*, evaluation stops immediately before Block A. This result also feeds into Block G's "Posting Freshness" signal later in the pipeline.

```bash
node check-liveness.mjs https://example.com/job/123

```

The command prints status icons (`✅`, `❌`, `⚠️`) with reasons; a non-active result terminates evaluation before any further processing.

### The Blacklist Gate

Career-Ops respects user-defined boundaries through the blacklist gate. Before any analysis begins, the system checks the posting's company against [`data/blacklist.md`](https://github.com/santifer/career-ops/blob/main/data/blacklist.md). If a match occurs, the evaluation halts and prompts the user for an explicit override. Any response other than "yes" terminates the pipeline.

This gate appears in [`modes/oferta.md`](https://github.com/santifer/career-ops/blob/main/modes/oferta.md) at lines 20-27, ensuring prohibited employers never reach the scoring stage unless explicitly approved by the candidate.

### Bounded Research Budget

To prevent runaway crawling, Career-Ops enforces a hard limit of **five external web searches** for legitimacy signals. This constraint, defined in [`modes/oferta.md`](https://github.com/santifer/career-ops/blob/main/modes/oferta.md) lines 29-38, ensures the assessment completes within predictable time and cost boundaries while gathering sufficient context for Block G analysis.

## Block G: Deep Legitimacy Analysis

If all gates pass, Block G aggregates multiple signals to assess job posting legitimacy. Located in [`modes/oferta.md`](https://github.com/santifer/career-ops/blob/main/modes/oferta.md), this stage produces a **Legitimacy tier** (`High Confidence`, `Proceed with Caution`, or `Suspicious`) displayed in the report header without affecting other block scores.

### Core Legitimacy Signals

Block G evaluates specific dimensions sequentially:

- **Posting Freshness**: Analyzes posting dates, apply-button states, and redirects (lines 38-44 of [`modes/oferta.md`](https://github.com/santifer/career-ops/blob/main/modes/oferta.md)).
- **Description Quality**: Checks for technology specifics, team size disclosures, and realistic requirements (lines 45-52).
- **Company Hiring Signals**: Detects recent layoffs or hiring freezes (lines 54-58).
- **Reposting Detection**: Identifies duplicate listings through scan-history analysis (lines 60-62).

### Specialized Compliance and Transparency Checks

Beyond basic signals, Block G scans for nuanced red flags that add non-scoring notes to help users calibrate trust:

- **Role Market Context** and **Employment Classification**
- **Buzzword vs. Infrastructure Mismatch**
- **Benefits-Terminology Mismatch** and **Location-Tag Mismatch**
- **Agency Licensing** (consulting [`templates/agency-licensing.yml`](https://github.com/santifer/career-ops/blob/main/templates/agency-licensing.yml))
- **Immigration-Status Requirements** (consulting [`templates/immigration-status-requirements.yml`](https://github.com/santifer/career-ops/blob/main/templates/immigration-status-requirements.yml))
- **Jurisdiction-Prohibited Content** (consulting [`templates/jurisdiction-prohibited-content.yml`](https://github.com/santifer/career-ops/blob/main/templates/jurisdiction-prohibited-content.yml))
- **Pay-Transparency Range-Width** and **Minimum-Wage Lawyer Prompt**
- **AI-Screening Disclosure**

These checks are enumerated sequentially in Block G (lines 63-119 of [`modes/oferta.md`](https://github.com/santifer/career-ops/blob/main/modes/oferta.md)).

## Critical Blockers That Halt Evaluation

Three specific conditions stop the pipeline before Block A:

1. **Dead Posting**: Detected when the liveness gate returns *expired*.
2. **Blacklisted Company**: Matches an entry in [`data/blacklist.md`](https://github.com/santifer/career-ops/blob/main/data/blacklist.md).
3. **User Decline**: Any response other than "yes" to a blacklist override prompt.

When none of these blockers fire, processing continues through Blocks A-F while preserving the final legitimacy tier for candidate reference.

## Implementation in Code

The liveness checker combines API and browser-based verification through modular helpers in `liveness-browser.mjs` and `liveness-api.mjs`.

*Programmatic integration example:*

```javascript
import { checkUrlLivenessWithFallback } from './liveness-browser.mjs';
import { chromium } from 'playwright';

async function isPostingLive(url) {
  const browser = await chromium.launch({ headless: true });
  const page = await newLivenessPage(browser);
  const { result } = await checkUrlLivenessWithFallback(page, url);
  await browser.close();
  return result === 'active';
}

```

This pattern mirrors the internal flow used by `auto-pipeline` and `oferta` modes. The [`modes/_shared.md`](https://github.com/santifer/career-ops/blob/main/modes/_shared.md) file holds the generic "Posting Legitimacy (Block G)" heading referenced across language-specific variants, ensuring consistency in how Career-Ops assesses job posting legitimacy across different regional implementations.

## Summary

- Career-Ops assesses job posting legitimacy through **Block G**, positioned after three protective gates in the A-G evaluation pipeline defined in [`modes/oferta.md`](https://github.com/santifer/career-ops/blob/main/modes/oferta.md).
- The **liveness gate** (`check-liveness.mjs`) filters expired postings using ATS APIs and Playwright browser checks, stopping evaluation immediately for dead links.
- A **blacklist gate** respects user preferences stored in [`data/blacklist.md`](https://github.com/santifer/career-ops/blob/main/data/blacklist.md), halting evaluation for prohibited companies unless explicitly overridden.
- **Bounded research** limits external searches to five queries, preventing runaway resource consumption while gathering necessary signals.
- Block G generates a **Legitimacy tier** (`High Confidence`, `Proceed with Caution`, or `Suspicious`) based on freshness, description quality, hiring signals, and compliance checks without altering underlying match scores in Blocks A-F.

## Frequently Asked Questions

### What happens if a job posting fails the liveness check in Career-Ops?

If `check-liveness.mjs` classifies a URL as *expired* or *uncertain*, the evaluation stops immediately before Block A. The system prints a status icon and reason to the console, preventing further processing of dead listings and conserving API credits.

### How does Career-Ops handle companies on the user blacklist?

Before substantive scoring, Career-Ops checks the company against [`data/blacklist.md`](https://github.com/santifer/career-ops/blob/main/data/blacklist.md). If matched, the pipeline halts and prompts for explicit user override. Any response other than "yes" terminates the evaluation, ensuring users never apply to deliberately excluded employers.

### Does the legitimacy tier affect the final match score in Career-Ops?

No. The **Legitimacy tier** generated by Block G appears in the report header for user guidance but does not influence the numerical scoring of Blocks A-F. It serves as a transparency layer to inform candidate prioritization and risk assessment.

### What file contains the detailed legitimacy signals for Block G?

The comprehensive list of legitimacy signals—including posting freshness, description quality, and compliance checks—is defined in [`modes/oferta.md`](https://github.com/santifer/career-ops/blob/main/modes/oferta.md) between lines 63-119, referenced by the `oferta` mode and shared across language-specific variants through [`modes/_shared.md`](https://github.com/santifer/career-ops/blob/main/modes/_shared.md).