Hermes Wiki
Developer/developer-scheduler

Developer Scheduler

Documents the recurring cloud routine that grows Developer automatically. Like architecture-scheduler and ai-digest-scheduler, this is a Claude Code cloud routine (Anthropic-hosted CCR session) created via the /schedule skill — a separate, isolated sandbox with its own git checkout of this repo, not part of the local Hermes nightly cron chain.

The 8-week enrichment sprint (2026-08-24 → ~2026-10-19)

Developer/ was scaffolded on 2026-08-24 with 35 topic folders / 255 leaf subtopics (see system_prompt) — empty README stubs at sprint start, until the same-day migration of all 108 Architecture/ notes gave 26 of the 35 topics real content immediately (see Developer/_index.md). To give the remaining topics — and ongoing depth on the migrated ones — real content fast, every other content-generating routine touching this vault was paused for 8 weeks so this one gets the budget:

  • Architecture Scheduler (trig_01CDFuy8NfboDcW1JpsCW87X) — disabled
  • AI Digest Scraper (trig_01SUbiwDdUyXrgKQvAGSBZZv) — disabled
  • Hermes incremental + monthly full-sweep synthesis (local cron) — commented out in crontab
  • Hermes nightly fix/lint/sync — kept, but moved from nightly (06:15 UTC daily) to weekend-only (06:15 UTC Sat/Sun) so lint/formatting hygiene doesn't lapse for 8 weeks
  • Weekend Vocab Scraper — already disabled since 2026-07-19, unaffected

Revert after ~2026-10-19 — ⚠️ gated on Mihir's explicit confirmation, not a standing instruction to act on once the date arrives (confirmed 2026-08-25): re-enable both cloud routines (enabled: true via RemoteTrigger//schedule), uncomment the two synthesis lines in crontab (backup at sprint-start saved to the operator's scratchpad — or just restore 0 5 * * * / 0 15 1 * *), and restore Hermes nightly to 15 6 * * * (every day). At that point, drop this routine's own cadence down per "After the sprint" below. Do not execute any of this — even after the date has passed — without Mihir explicitly confirming in that conversation first; he's tracking the date himself and will raise it when ready. Noticing the date has passed is not authorization on its own.

Separately, and on a different timeline: this is not the same event as the Coverage rotation reaching random mode (all 10 passes done) — see system_prompt. That's completion-based (realistically ~15 weeks from 2026-08-25, well past this sprint's Oct 19 end date), not tied to this date at all. Don't conflate the two.

2026-08-24: switched to one-file-per-note (same day as sprint start)

Content was briefly written as one accumulating file per subtopic/flavor (Fundamentals.md etc. with dated ## sections appended over time). Abandoned before the second scheduler run in favor of Architecture/'s proven convention — a directory per flavor, one file per note — because a single growing file per subtopic doesn't scale across an 8-week sprint plus ongoing growth after it (unwieldy to edit/link/diff). All 108 notes migrated from Architecture/ on 2026-08-24 already landed in this one-file-per-note shape from the start.

What it does, during the sprint

8x/day, every 3 hours, at 00:00/03:00/06:00/09:00/12:00/15:00/18:00/21:00 UTC (0 0,3,6,9,12,15,18,21 * * *) — bumped from 2x/day on 2026-08-25, since no other routine is competing for this repo's write budget during the sprint. The routine:

  1. Reads system_prompt in full — topic-first structure, the one-file-per-note flavor-directory convention, pillar tags, the ## Engineering Lens rules, the "Depth bar — calibrated against Architecture/" section (reads Architecture/Fundamentals/circuit-breaker-pattern.md as its concrete quality reference every run), and the "Coverage rotation" section (mechanics reference — the live state lives in step 2).
  2. Reads writelist for sources, pillar tags, and — critically — the "Coverage rotation" section's live state: current_pass, current_flavor, pass_cursor, "Skipped this pass". If current_pass is the literal string random: rotation has finished (all 10 passes complete); fall back to the pre-rotation behavior — scan every leaf subtopic's completeness and pick freely across topic/subtopic/flavor by best-available material, same as this step used to work before 2026-08-25. Otherwise, rotation is active — proceed with steps 3-4 below instead of freely picking.
  3. (Rotation active only) Recompute the canonical 255-leaf order fresh from the filesystem (topic-alphabetical, then subtopic-path-alphabetical within each topic — never trust a stale hardcoded list, since hand-added subtopics slot in automatically this way). Find pass_cursor's position in that list (or start at index 0 if pass_cursor is (none — pass not yet started)), and work forward from there: for each subsequent leaf, check whether it already has an entry for current_flavor — if it does, skip past it silently (already covered this pass, e.g. from a manual note added between runs) and continue; if it doesn't, that's a candidate to write.
  4. Hard cap: at most 4 notes per run, and only if each one can genuinely clear the depth bar (~600-1200 words, real tradeoff table, real Sources). 2-3 notes is a normal, expected run — never stretches to hit a quota. (Rotation active) Attempt candidates from step 3 in order; a candidate that can't clear the depth bar for current_flavor gets logged to writelist.md's "Skipped this pass" (not written) and the walk continues to the next candidate — a run should still make forward progress even if one subtopic lacks material. Whether written or skipped, update pass_cursor to the last leaf processed this run. If the walk reaches the end of the canonical list, the pass is complete: move "Skipped this pass" entries into the cumulative "Revisit log" (each with pass/flavor/date), advance current_pass to the next row in system_prompt's table (or to random after pass 10), and reset pass_cursor. (Rotation finished / random mode) picks fully-untouched subtopics first (breadth), preferring ones with genuinely strong material over ones it'd have to stretch for — same free-form logic as before rotation existed.
  5. (Rotation active) Flavor for every note this run is current_flavor — no mixing, that's the entire point of a pass. Checklists stays opportunistic and outside the rotation (write one only if a subtopic obviously warrants it, never as a rotation candidate). (Random mode) Flavor mix roughly matches Architecture/'s realized ratio (about half Fundamentals, a third CaseStudies, the rest Challenges/Checklists) rather than forcing all four per subtopic. Either mode: CaseStudies always need a real, findable source; Challenges keep "Mihir's attempt" as a never-fabricated > [!todo] placeholder.
  6. Writes each note as its own new file inside the relevant flavor directory (creating the directory if needed), kebab-case filename from the title, own frontmatter, plain ## sections (not nested under anything) — never edits or appends to an existing note file.
  7. Updates the subtopic's own README.md (Research questions answered/refined) if warranted. Index updates are mandatory on every run that writes a note, not optional — this is a two-tier index (split 2026-08-24 — see Developer/_index.md for why):
    • Topic index (Developer/<Topic>/_index.md): add/update the entry for every topic that got a new note, grouped by subtopic, same shape as the existing entries — create the file from scratch, matching another topic's _index.md format, if the topic doesn't have one yet.
    • Hub tree (Developer/_index.md, ## Full topic tree section): for every leaf subtopic (and sub-subtopic) that gained a note, update its line in the nested tree — bump *(empty)* to — 1 note, or increment an existing count. If a node has both a note count and children (e.g. Caching — 1 note directly), update the "directly" count, not a child's. Roll the new count up to every ancestor line too (its own topic-level total, and any intermediate subtopic that also shows a count). A fully-empty topic's first note also moves it into the topic-index-linked form ([[Topic/_index\|index]]) instead of the bare *(empty)*.
    • The hub's summary line ("N notes across M topics...") gets its numbers bumped too when they change.
    • Never add per-note listings to the hub tree — titles/links live only in the topic-level index; the tree only ever shows folder names and counts.
  8. Logs the run, every run, unconditionally: prepends a ## [YYYY-MM-DD HH:MM UTC] Developer Scheduler block to Logs/2026.md with a [DEVELOPER] bullet listing exactly which notes were written (subtopic + flavor + filename), any subtopics skipped this run (path + reason), or no qualifying content this run. If a pass completed this run, add a [DEVELOPER] bullet calling that out explicitly (e.g. Pass 3 (Challenges) complete — N skipped, moved to Revisit log — starting Pass 4 (CaseStudies)), so pass transitions are visible in the log without having to diff writelist.md.
  9. Commits — new note files, updated READMEs/topic _index.md/hub _index.md, writelist.md (rotation state changes every run while rotation is active — always include it, even on a quiet run where the only change is pass_cursor moving past skipped subtopics), and Logs/2026.md (always) — together, and pushes directly to master. No PR gate. Commit message: developer: N notes added (HH:MM UTC) or developer: log entry, no new content (HH:MM UTC) on a quiet run.

Scope guard: only ever touches files under Developer/, plus the shared Logs/2026.md entry.

After the sprint

Once the 8-week window ends and the other routines resume, drop this routine's cadence back down (e.g. to 1x/day, at a slot clear of Hermes 05:00/06:15, AIDigest 11:00, and Architecture's 17:00 UTC). The breadth→depth handoff described in earlier versions of this section is superseded by the Coverage rotation system (added 2026-08-25) — the rotation already sequences breadth (pass 1: Fundamentals) and depth (passes 2-10: CaseStudies/Challenges) automatically, so there's no separate manual handoff to make. Just let the rotation keep running at whatever cadence is set; if it's still mid-pass when the sprint ends, it resumes exactly where pass_cursor left off at the reduced cadence. Only revisit the cadence, not the picking logic, unless current_pass has reached random (all 10 passes done) — at that point, decide whether to re-run the 10-pass sequence again or stay in random mode.

Configuration

Field Value
Routine name Developer Scheduler
Routine ID trig_01N78r24FWUQEhoVPRRywnZq
Cadence 0 0,3,6,9,12,15,18,21 * * * — every 3 hours, 8x/day (bumped from 2x/day on 2026-08-25), for the 8-week sprint only
Model claude-sonnet-5
Repo https://github.com/fullstackfusions/PKM (master branch, direct push)
Environment Anthropic cloud default (env_01S8gzx6qMrwgKjVjq6ygeiD)
Tools Bash, Read, Write, Edit, Glob, Grep, WebSearch, WebFetch
Scope guard Only ever modifies files under Developer/, plus the shared Logs/2026.md
Hermes Wiki