← back to AbramsEgo
build-queue/done/23-cron-model-from-script.md
28 lines
# AbramsEgo task 23 — cron cards: derive model from the INVOKED SCRIPT (0/114 populated today)
Read SPEC.md. Panel 4 requires every scheduled job to show its **model**. Task 20 added the
`model` field + card rendering, but the parser (`server.js` `readCronPlistMeta()`, ~lines 257-261)
only greps the **plist XML** for `--model` / `claude-*` tokens — and NO com.steve.* plist carries
one (verified 2026-07-01: 0 of 114 jobs have a model). The models live one hop away, in the
script the plist invokes: e.g. `com.steve.abramsego-loop` → its bash script contains
`claude-fable-5`; `com.steve.yolo-queue-loop` → `claude-opus-4-8`; `com.steve.dwphoto` → a
`--model` arg. So the model line on every cron card is a dead placeholder in practice. ~12 min.
1. In `readCronPlistMeta()` (`server.js:223`), after the existing plist-XML model match fails:
- Resolve the invoked script: from `ProgramArguments`, take the first arg that starts with `/`
and ends in `.sh|.js|.cjs|.mjs|.py` (skip `/bin/bash`, `/usr/bin/env` etc.); fall back to the
last arg if it's an existing file path.
- If the file exists and is < 512 KB, read it and reuse the SAME two regexes already at lines
258-259 (`--model` arg form adapted for shell: `/--model[= ]["']?([\w.-]+)/` + the
`claude-(?:opus|sonnet|haiku|fable)[\w.-]*` token). First hit wins → `meta.model`.
- Keep it synchronous + try/catch'd like the rest of the function — never throw, degrade to null.
2. `pm2 restart abramsego`, then verify:
`curl -s -u admin:'DW2024!' http://127.0.0.1:9773/api/data | node -e 'let d="";process.stdin.on("data",c=>d+=c).on("end",()=>{const j=JSON.parse(d).crons.jobs.filter(c=>c.model);console.log(j.length,"jobs with model:",j.slice(0,5).map(c=>c.label+"="+c.model))})'`
— expect ≥3 jobs (abramsego-loop=claude-fable-5, yolo-queue-loop=claude-opus-4-8, dwphoto…).
Load http://127.0.0.1:9773/ and confirm those cron cards show the model on the runs line.
3. Commit:
`git add -A && git commit -m "fix: cron cards derive model from invoked script (was 0/114 populated)" --author="Steve <steve@designerwallcoverings.com>"`
Do NOT touch the card render (already done in task 20). Jobs whose script genuinely names no
model correctly stay null — don't invent one. Local only, no deploy.