Finds open conference CFPs relevant to the user across Java/AI/developer conferences, with persistent sent/dismissed/remind state and source-aware Sessionize verification. NanoClaw per-chat overlay tile.
70
87%
Does it follow best practices?
Impact
—
No eval scenarios have been run
Advisory
Suggest reviewing before use
cfp-run/Referenced from check-cfps SKILL.md (Resume guard). Per coding-policy: stateful-artifacts, every stateful artifact ships a schema document next to its owner skill; this file is that document for the run-state checkpoint store — the per-stage scratch artifacts check-cfps writes so an interrupted run resumes from disk.
/workspace/group/state/cfp-run/ (overrideable per-process via the CFP_RUN_STATE_DIR env var, used by tests). A flat directory:
cfp-run/
manifest.json run bookkeeping
fetch.json saved stage artifacts (one file per saved stage)
candidates.json
prep.json
sessionize_results.json
decisions.json
working_set.jsontessl__check-cfps (this skill). Written and cleared exclusively by scripts/run-state.py. The wrapper nightly-cfp-sync never touches it — it calls check-cfps, which manages its own run-state internally.
scripts/run-state.py load <stage> only. No other skill or script reads these artifacts; they are scratch state for a single in-flight run, distinct from cfp-state.json (the durable, owned CFP data).
{
"schema_version": 1,
"run_date": "2026-06-13",
"completed": ["fetch", "candidates", "prep"]
}| Field | Type | Required | Description |
|---|---|---|---|
schema_version | integer | yes | Currently 1. Bump on shape change. begin resumes only when this equals the supported version; a mismatch (future/partial shape) is treated as no usable prior run and resets. |
run_date | string | yes | UTC date (YYYY-MM-DD) the run began. begin resumes only when this equals today; otherwise it resets. |
completed | string[] | yes | Stage names saved so far, in completion order, deduped. |
The check-cfps pipeline checkpoints these stages in order. Each is the JSON artifact a step already produces — save it as soon as the step yields it, so the next continuation resumes from the first stage NOT in completed.
| Stage | Produced after | Artifact |
|---|---|---|
fetch | Step 3 fetch script | check-cfps-fetch.py stdout ({cfps, warnings, checked_at}) |
candidates | Steps 2–4 merge | the merged, slug-deduped candidate pool (Sessionize + fetch + web-search) |
prep | Step 5 prepare | prepare-sessionize-batch.py stdout ({slugs, sessionize, non_sessionize, unverifiable, counts}) |
sessionize_results | Step 5 MCP call | the sessionize_get_events array |
decisions | Step 5 apply | apply-sessionize-results.py stdout ({decisions, summary}) |
working_set | Steps 5–7 | the in-memory entry set (verified + relevance + travel applied) about to be written in Step 8 |
Stage names are free-form lowercase identifiers ([a-z0-9][a-z0-9_-]*); the table above is the check-cfps contract, not a hard-coded enum in the script.
# Start or resume. Resets across a UTC-day boundary; resumes within the same day.
python3 .../run-state.py begin
# -> {"resume": false, "run_date": "2026-06-13", "completed": []}
# -> {"resume": true, "run_date": "2026-06-13", "completed": ["fetch", "prep"]}
# Persist a stage artifact (JSON on stdin).
echo '<artifact json>' | python3 .../run-state.py save prep
# -> {"saved": "prep"}
# Reload a saved stage on resume.
python3 .../run-state.py load prep # prints the artifact; exit 2 if never saved
# Clear on success (end of Step 8, after the state write + stampers).
python3 .../run-state.py done # -> {"cleared": true}begin finds no usable manifest (absent, unreadable, stale run_date, or unsupported schema_version), clears any leftover files, writes a fresh manifest, returns resume: false. The agent runs Steps 2–8, calling save <stage> as each artifact appears.begin finds today's manifest and returns resume: true with completed. The agent loads each completed stage instead of recomputing it and resumes at the first uncompleted stage.done to remove the directory. The next run starts clean.done; artifacts persist so a same-day retry resumes. A retry on a later UTC day resets to a fresh full run.Resume is best-effort: a fresh full run is always safe (it does not depend on any saved artifact), so a missing or reset store only costs redone work, never correctness.