jobseek-label-daily — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited jobseek-label-daily (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
This routine samples public job postings from the last 24 hours, labels them with Codex project custom agents, validates the outputs, merges accepted records, and uploads accepted gold data to viktoroo/jobseek-postings-labelled.
The Python labeller code is deterministic orchestration only: database reads, Jinja task rendering, JSON Schema/custom validation, merge, QA, and HuggingFace upload. Do not add provider SDK calls or call OpenAI or Anthropic endpoints from apps/crawler/src/labeller. LLM judgment happens through the already-running, subscription-backed Codex session and project custom agents in .codex/agents/.
Use these project custom agents:
jobseek-labeller-normalizer: raw HTML task input -> normalized.html.jobseek-labeller-splitter: split_sections task input -> split-out.json.jobseek-labeller-extractor: extract_all task input -> extract-all-out.json.Each agent invocation message must be exactly:
INPUT: <rendered-input-path>
OUTPUT: <output-path>The Jinja task prompts in apps/crawler/src/labeller/prompts/tasks/ own task-specific rules and schema phrasing. Do not duplicate or rewrite those prompts in the orchestrator.
Run commands from apps/crawler with uv run labeller .... Default RUN_DATE is today; default SAMPLE_SIZE is 24 unless the user provides overrides.
uv run labeller sample --date "$RUN_DATE" --count "$SAMPLE_SIZE" \
--out "data/postings-labelled/_runs/$RUN_DATE/sample.json"RUN_DIR=data/postings-labelled/_runs/$RUN_DATE/$POSTING_ID.uv run labeller prepare-pre-llm "$POSTING_ID" --date "$RUN_DATE"Skip the posting if the command exits non-zero.
uv run labeller render-task --task normalize_html \
--input "$RUN_DIR/raw_input.json" \
--out "$RUN_DIR/normalize-in.md" \
--output-path "$RUN_DIR/normalized.html"Invoke jobseek-labeller-normalizer with the two-line INPUT/OUTPUT message. Then check that normalized.html exists, is non-empty, and starts with <.
uv run labeller prepare-post-llm "$POSTING_ID" --date "$RUN_DATE"Skip the posting if coverage validation fails.
uv run labeller render-task --task split_sections \
--input "$RUN_DIR/input.json" \
--out "$RUN_DIR/split-in.md" \
--output-path "$RUN_DIR/split-out.json"Invoke jobseek-labeller-splitter, then validate:
uv run labeller validate --kind sections \
--file "$RUN_DIR/split-out.json" \
--context "$RUN_DIR/input.json"On validation failure, re-render with --previous-error "<validator output>" and retry the same agent up to two times.
uv run labeller render-task --task extract_all \
--input "$RUN_DIR/input.json" \
--sections "$RUN_DIR/split-out.json" \
--out "$RUN_DIR/extract-all-in.md" \
--output-path "$RUN_DIR/extract-all-out.json"Invoke jobseek-labeller-extractor, then validate:
uv run labeller validate --kind extract_all \
--file "$RUN_DIR/extract-all-out.json" \
--context "$RUN_DIR/input.json"Use the same two-retry protocol on validation failure.
uv run labeller merge --posting "$POSTING_ID" --date "$RUN_DATE" \
--verdict accepted \
--out "data/postings-labelled/postings/$RUN_DATE/$POSTING_ID.json"
uv run labeller validate --kind posting \
--file "data/postings-labelled/postings/$RUN_DATE/$POSTING_ID.json"
uv run labeller validate --kind qa \
--file "data/postings-labelled/postings/$RUN_DATE/$POSTING_ID.json" \
--report "$RUN_DIR/qa.json"If merge or final validation cannot be repaired, use labeller merge --verdict rejected --rationale "<reason>" rather than hand-crafting a record. If QA fails after a valid merge, update only labelling_meta.qa_verdict and labelling_meta.qa_rationale from the QA report.
uv run labeller upload --date "$RUN_DATE"Use --dry-run for upload verification.
The older per-section extractors (extract_team, extract_role, extract_requirements, extract_preferred, extract_benefits, extract_globals) remain available for compatibility. Prefer extract_all unless the user explicitly asks for granular retries or debugging of a specific section kind.
For changes to this orchestration surface, run:
git status --short
uv run --with 'pyyaml>=6' python /Users/Viktor/.codex/skills/.system/skill-creator/scripts/quick_validate.py .agents/skills/jobseek-label-daily
python3 - <<'PY'
import pathlib, tomllib
for path in sorted(pathlib.Path(".codex/agents").glob("*.toml")):
data = tomllib.loads(path.read_text())
assert set(data) == {"name", "description", "developer_instructions"}, path
assert "model" not in data, path
print("codex agents valid")
PY
legacy_terms="$(printf '%s' 'son' 'net|op' 'us|Agent[(]|[.]Codex|Claude Code ' 'session|Anthropic ' 'API')"
rg -n "$legacy_terms" .codex .agents .claude || true
cd apps/crawler && uv run labeller --helpDo not run expensive uploads as verification.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.