Getting it into your agent
One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.
npx agentmods add agents/strelov1/freehire/job-lifecyclegit clone --depth 1 https://github.com/strelov1/freehireWhat it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5 | $0.00000 | $0.03728 |
| Opus 5 | $0.00000 | $0.01864 |
| Sonnet 5 | $0.00000 | $0.00746 |
| Haiku 4.5 | $0.00000 | $0.00373 |
Grade A, and why
job-lifecycle scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured yesterday.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Nothing flagged
None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.
How it starts
The opening of the file, as written. The whole thing — 81 lines — stays where its author put it; the contents beside it link to each section on GitHub.
Job lifecycle conventions
Scope
The open/closed state of a job row, the four mechanisms that write closed_at, and the filtering semantics that depend on it.
Always true
- A job is open while
closed_at IS NULL. Closing is a soft state, and the lifecycle never deletes. - The one exception is
cmd/prune(catalogue pruning), which hard-deletes jobs that do not belong on an IT job board. It is a deliberate, operator-driven campaign, not part of the lifecycle:closed_atkeeps meaning "the employer took this down", and "not our profile" is expressed by the row being gone and archived inpruned_jobs. Overloadingclosed_atwith the second meaning would corrupt a signal three mechanisms already write. - A closed row keeps its
public_slug, enrichment, anduser_jobsreferences, and reopens for free. - List, search, and company surfaces filter
closed_at IS NULL. Detail still serves a closed job (withclosed_at) so links and history don't break. - The ingest write stamps
last_seen_aton every crawl —RefreshUnchangedJobwhen the posting is unchanged,UpsertJobotherwise; the post-run sweep closes a provider's jobs unseen for 48h. - A reappearing posting reopens via the upsert.
- Self-closing sources (
jobtech, etc.) are excluded from the unseen sweep — the feed'sremovedevents are the authoritative close signal. - The liveness worker closes only on positive evidence (two consecutive
expiredreads) and never reopens. - A source carrying no close signal at all — no re-crawl, no feed, and a URL that outlives the vacancy — is closed by age instead:
telegramtoday, at 45 days. It is the only close that rests on a guess. - Every close records WHICH mechanism wrote it in
closed_reason; a reopen clears it. Rows closed before that column existed carry'', meaning unknown, and are never relabelled.
How it works
Closing is a soft state on one column (closed_at) written by four independent mechanisms, each covering a gap the others can't reach. Three of them close on evidence; the fourth, the age rule, closes on a guess, which is why every close now records which one wrote it.
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- yesterday First seen · 81 lines · 0 tokens per session scan A 866daa6d4334
job-lifecycle is an agent published in the GitHub repository strelov1/freehire (533 stars, last pushed 3d ago), licensed MIT. It costs nothing until one of its globs matches a file; then it loads 3,728 tokens. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-30.
Other agents, from other repositories
jobseek-labeller-extract-benefits
Extract structured fields from the benefits section — salary, equity, remote policy, visa sponsorship, annual leave, parental leave, learning budget, perks. Invoked once per posting that has a benefits section.
jobseek-labeller-extract-globals
Derive cross-section labels — profession (English), seniority (English free-text), employment type, locales, locations. Invoked once per posting after all per-section extractors have run.
jobseek-labeller-extract-requirements
Extract structured fields from the requirements section — years of experience, education, skills with category, certifications, physical requirements, clearance/licenses/background check. Invoked once per posting that has a requirements section.
jobseek-labeller-extract-role
Extract structured fields from the role section — role summary, responsibilities, collaboration partners, shift/hours/travel/on-call. Invoked once per posting that has a role section.
jobseek-labeller-extract-team
Extract structured fields from the team section of a labelled job posting — team name, team function tags. Invoked once per posting that has a team section.
jobseek-labeller-extract-preferred
Extract structured fields from the preferred section — preferred skills with category, preferred education, preferred certifications. Invoked once per posting that has a preferred section.