How `rejection-latency.mjs` Signals Companies Exceeding 30-Day Post-Interview Silence

rejection-latency.mjs in santifer/career-ops detects silent employers by comparing the most recent interview date to a configurable 30-day courtesy threshold, then emits JSON or markdown suggestions for manual blacklisting without ever writing to files.

The rejection-latency.mjs utility addresses a common job-search frustration: companies that interview candidates then disappear. As implemented in santifer/career-ops, this tool implements a suggest-only contract—it identifies post-interview silence exceeding the default 30-day window but leaves all decisions to the user. This article explains the detection mechanism, output formats, and practical workflows.


How the 30-Day Silence Detection Works

The script operates as a pure analyzer across two data sources, never modifying any files.

Data Sources and State Matching

rejection-latency.mjs cross-references two markdown ledgers:

The script loads every Interview-state entry, then extracts the latest interview round date from the corresponding active-interviews record (the most recent timestamp in the interview notes).

Date Comparison and Threshold Logic

For each candidate record, the script calculates the delta between the last interview date and the reference date:

// Conceptual flow based on source lines 38-45 of rejection-latency.mjs
const daysSilent = calculateDays(lastInterviewDate, referenceDate);
const threshold = options.courtesyDays || 30;  // default: 30 days

if (daysSilent > threshold) {
  emitSignal(companyRecord);  // Generate suggestion only
}

The default courtesy window is 30 days, defined in the script header. Users can override this with --courtesy-days <N> for stricter or more lenient thresholds.

Suggest-Only Output Design

Per the contract documented in AGENTS.md at line 114, the tool never writes to disk. It emits signals through stdout in two formats:

Format Flag Output
JSON (machine-readable) (default) Array of objects with company, role, lastInterviewDate, daysSilent, and ready-to-paste blacklist line
Markdown table --summary Human-readable table with Add to blacklist snippets

CLI Commands and Practical Workflows

Basic Usage Patterns

Generate the default JSON report for programmatic processing:

node rejection-latency.mjs

Produce a review-ready markdown table:

node rejection-latency.mjs --summary

Adjust the silence threshold to 45 days:

node rejection-latency.mjs --courtesy-days 45 --summary

Evaluate against a fixed date for deterministic testing:

node rejection-latency.mjs --today 2026-07-17 --summary

Run the built-in test suite (includes a 217-day silent fixture case):

node rejection-latency.mjs --self-test

Typical Blacklisting Workflow


# Step 1: Generate human-readable report

node rejection-latency.mjs --summary > latency-report.md

# Step 2: Review suggested entries

cat latency-report.md

# Step 3: Manually copy desired blacklist lines to data/blacklist.md

# (No automated write occurs—user controls all changes)

Key Configuration Options

Option Default Purpose
--courtesy-days <N> 30 Days of silence before triggering a signal
--today <ISO-date> System date Reference date for calculations (testing/reproducibility)
--summary false Output markdown table instead of JSON
--self-test false Execute validation against fixture data

Source File Architecture

Understanding the file relationships clarifies how silence detection integrates with the broader career-ops system:

File Function Source Link
rejection-latency.mjs Core silence detection and signal generation View source
data/active-interviews.md Interview round dates and progress notes View source
data/applications.md Application state ledger (Interview filter source) View source
data/blacklist.md Manual destination for rejected companies View source
AGENTS.md Tool contract documentation (line 114) View source
docs/SCRIPTS.md CLI usage examples (line 466) View source

Summary

  • rejection-latency.mjs scans data/active-interviews.md and data/applications.md for Interview-state entries with stale activity
  • The 30-day courtesy threshold is configurable via --courtesy-days and compares the latest interview round date to today (or --today)
  • Output is strictly suggest-only—JSON or markdown tables emitted to stdout, with no file modifications
  • Users manually review signals and optionally append entries to data/blacklist.md
  • The tool honors the non-writing contract specified in AGENTS.md and supports deterministic testing via date overrides

Frequently Asked Questions

What happens if a company has multiple interview rounds?

The script extracts the most recent timestamp from the interview notes field in data/active-interviews.md. Only the latest round date matters for silence calculation—earlier rounds are ignored.

Can I automate the blacklisting process?

No—by design. The suggest-only contract in AGENTS.md (line 114) explicitly prohibits unattended writes. Users must manually copy suggested entries to data/blacklist.md, ensuring intentional decisions about each company.

How does --today differ from the actual current date?

The --today flag accepts an ISO-formatted date (e.g., 2026-07-17) that replaces the system clock for all calculations. This enables reproducible reports and testing scenarios, such as verifying how the tool would have behaved on a past date.

What companies are excluded from detection?

Any application not in the Interview state in data/applications.md is automatically excluded, regardless of data/active-interviews.md content. Additionally, companies with silence at or below the courtesy threshold (default 30 days) generate no signal.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →