Weekly progress tracking for key product and growth milestones — celebrates crossings, alerts on approaches, surfaces stalls
Install
npx skillscat add atrium-hermes/atrium-lighthouse/milestone-tracker Install via the SkillsCat registry.
Today is ${today}. Read memory/MEMORY.md before starting.
Goal
Track progress toward defined milestones across repos, system capabilities, and product goals. Milestones live in memory/milestones.md. Each run: fetch current state, compare to last recorded, classify status, notify on anything notable.
One skill, one job: are we moving?
Steps
1. Load milestone config
Read memory/milestones.md. If it doesn't exist, create it with the seed config below and continue.
Seed config (write to memory/milestones.md if missing — replace placeholder rows with the operator's actual targets):
# Milestones
*Last run: never*
| ID | Label | Target | Baseline | Last | Status |
|----|-------|--------|----------|------|--------|
| ms-01 | Example repo stars | stars:owner/repo:1000 | 0 | 0 | on-track |
| ms-02 | Enabled skills | skills:30 | 0 | 0 | on-track |Parse the table: each row is one milestone. The Target field encodes the data source:
stars:{owner}/{repo}:{target_count}— GitHub star countskills:{target_count}— count skills withenabled: truein aeon.ymlmanual:{label}— operator-maintained, status updated by hand
2. Fetch current state
For star milestones, use gh api to get current star counts:
gh api repos/${owner}/${repo} --jq '.stargazers_count'If gh api fails on a repo (private, rate limit, etc.): fall back to the Last value from the config — don't fail the whole run.
For skills milestones, count enabled skills:
grep -c 'enabled: true' aeon.ymlFor manual milestones, leave Last unchanged and use the operator-set status.
3. Classify each milestone
For each milestone, compute:
current— fetched value from step 2delta—current - last(change since last run)pct—(current / target) * 100weeks_stalled— ifdelta == 0, check how many consecutive weekly runs haddelta == 0(stored in theStatusfield asstalled-N)
Then classify:
| Condition | Status |
|---|---|
current >= target AND last < target |
crossed — just hit it this run |
current >= target AND last >= target |
done — already crossed, skip |
pct >= 90 |
approaching — within 10% of target |
delta == 0 AND weeks_stalled >= 2 |
stalled — no movement in 2+ weeks |
| otherwise | on-track |
Skip milestones with status done — don't re-celebrate or re-alert.
4. Decide whether to notify
- Nothing notable (all
on-trackordone): logMILESTONE_TRACKER_OK: no alertsand skip notification. - Any
crossed,approaching, orstalled: send notification.
5. Format notification
Write to .pending-notify-temp/milestone-tracker-${today}.md (create dir if needed), then:
./notify -f .pending-notify-temp/milestone-tracker-${today}.mdFormat (if soul files are populated, match that voice; otherwise use a clear, direct, neutral tone):
milestone check — ${today}
{IF any crossed}
crossed:
{forEach crossed}
- {label}: {current}/{target} — done
{end}
{IF any approaching}
approaching:
{forEach approaching}
- {label}: {current}/{target} ({pct}%)
{end}
{IF any stalled}
stalled ({weeks_stalled}w no movement):
{forEach stalled}
- {label}: {current}/{target} — stuck at {pct}%
{end}
{IF any on-track with delta > 0}
moving this week:
{forEach on-track with delta > 0}
- {label}: +{delta} → {current}/{target}
{end}No empty sections. If crossed is empty, omit it entirely. Same for the others.
6. Update memory/milestones.md
Rewrite the table with:
- Updated
Lastvalues (current state) - Updated
Statusvalues (new classification) - Updated header:
*Last run: ${today}*
For stalled milestones, encode the count: stalled-{N} (e.g., stalled-2 means no movement for 2 consecutive runs).
For done milestones (crossed and staying crossed), set status to done:{crossed_date} (e.g., done:2026-05-12).
7. Log to memory/logs/${today}.md
Append:
## Milestone Tracker
- **Milestones checked:** {total}
- **Crossed:** {list or "none"}
- **Approaching:** {list or "none"}
- **Stalled:** {list or "none"}
- **On-track with movement:** {count}
- **Notification:** sent / skipped
- MILESTONE_TRACKER_OKSandbox Note
Uses gh api for GitHub star counts — gh CLI handles auth internally, no env-var expansion needed. grep on aeon.yml is local-only. No external network beyond GitHub API.
Required Env Vars
None — gh CLI uses the workflow's GITHUB_TOKEN automatically.
Adding Milestones
Add rows to memory/milestones.md. Supported target formats:
stars:{owner}/{repo}:{N}— repo star countskills:{N}— enabled skills in aeon.ymlmanual:{label}— operator-maintained text milestone; update status by hand in the file