[object Object]

← back to AbramsEgo

harness: rate-limit-aware loop + StartInterval heartbeat + SPEC anchor + reseeded queue

785c4e57117f56f6e6be4f93706f13281d9c5104 · 2026-07-01 10:40:15 -0700 · Steve

- build-loop.sh: detect Max session-limit/overload; leave task queued + clean rest instead of
  shredding it into failed/ (root cause of the 10:20 mass-fail). Smart 'always restart'.
- plist: add StartInterval=600 heartbeat so the loop auto-resumes after any clean rest
  (empty queue or rate-limit) — fixes the post-reset stall.
- SPEC.md: command-center target + Steve hard rules (created date+time, sort+density, costs, gated).
- build-queue: requeue 3 valid tasks + add 04/05/06 feature tasks + 99 bounded replenisher.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

Files touched

Diff

commit 785c4e57117f56f6e6be4f93706f13281d9c5104
Author: Steve <steve@designerwallcoverings.com>
Date:   Wed Jul 1 10:40:15 2026 -0700

    harness: rate-limit-aware loop + StartInterval heartbeat + SPEC anchor + reseeded queue
    
    - build-loop.sh: detect Max session-limit/overload; leave task queued + clean rest instead of
      shredding it into failed/ (root cause of the 10:20 mass-fail). Smart 'always restart'.
    - plist: add StartInterval=600 heartbeat so the loop auto-resumes after any clean rest
      (empty queue or rate-limit) — fixes the post-reset stall.
    - SPEC.md: command-center target + Steve hard rules (created date+time, sort+density, costs, gated).
    - build-queue: requeue 3 valid tasks + add 04/05/06 feature tasks + 99 bounded replenisher.
    
    Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---
 SPEC.md                                          | 35 ++++++++++++++++++++++++
 build-queue/STOP                                 |  0
 build-queue/tasks/04-model-usage-subagents.md    | 15 ++++++++++
 build-queue/tasks/05-git-activity-feed.md        | 14 ++++++++++
 build-queue/tasks/06-hardrule-compliance-pass.md | 18 ++++++++++++
 build-queue/tasks/99-replenish.md                | 17 ++++++++++++
 scripts/build-loop.sh                            |  7 +++++
 7 files changed, 106 insertions(+)

diff --git a/SPEC.md b/SPEC.md
new file mode 100644
index 0000000..5cb41f6
--- /dev/null
+++ b/SPEC.md
@@ -0,0 +1,35 @@
+# AbramsEgo — Build Spec (the target the autonomous loop builds toward)
+
+**What it is:** an Abrams-branded **AI-agent command center** — a single local page that
+gives immediate situational awareness across Steve's whole agent fleet, so he never has to
+hop between terminals/CNCP/pm2/launchd to know the state of the operation. Design north-star
+is the `@androoagi` "AI Agent Environment Tour" (OpenClaw-style mission control).
+
+Runs under pm2 as **`abramsego`** on **:9773**, Basic Auth `admin:DW2024!`. Local only.
+
+## Panels (the command-center surface)
+1. **Top metrics bar** — live CPU / RAM / swap / disk, color-coded by threshold; always on.
+2. **Fleet health** — pm2 (Mac2 + Kamatera) up/down counts, launchd job status, gateway/uptime.
+3. **Cost & energy P&L** — today / all-time / projected-monthly from `~/.claude/cost-ledger.jsonl`;
+   per-provider donut; the 4 gated revenue engines with `gated`/`live` pills (money = GATED).
+4. **Cron / launchd status** — every scheduled job: status, schedule, last/next run, model.
+5. **Sessions & sub-agent runs** — active Claude sessions, recent sub-agent runs, model usage.
+6. **Activity feed** — recent git commits across `~/Projects`, recent wins (CNCP), canary verdicts.
+7. **AI chat** — natural-language queries over costs/sessions/crons/config.
+8. **Auto-refresh** — stale-while-revalidate snapshot; live without reload.
+
+## Steve's HARD rules this build must satisfy (from global CLAUDE.md)
+- **Admin cards show created DATE + TIME** (`🕓 May 20, 2026, 3:17 AM`, `toLocaleString`, visible on
+  the card, full ISO in `title=`). AbramsEgo is an admin surface → every card/tile obeys this.
+- **Any product/list grid gets sort + density slider + infinite scroll** (localStorage-persisted).
+- **Always show costs** — every paid-API figure surfaced; free/local labeled `$0 (local)`.
+- **Gitify** — commit after each success (author `steve@designerwallcoverings.com`).
+
+## GATED — draft to `~/.claude/yolo-queue/pending-approval/`, never execute
+Deploy to Kamatera, DNS/domain, Stripe/pricing/publish, send-to-list, spend, remote push,
+canonical `dw_unified` writes. Each gated step → officer APPROVE/REVISE/BLOCK memo.
+
+## Build discipline for the loop
+- One task = one self-contained, <15-min chunk. Test against the RUNNING pm2 instance
+  (`pm2 restart abramsego` + curl :9773) — never start a second node on 9773.
+- Use `/dtd` to decide judgment calls. Commit on success. Leave gated work as drafts.
diff --git a/build-queue/STOP b/build-queue/STOP
deleted file mode 100644
index e69de29..0000000
diff --git a/build-queue/tasks/04-model-usage-subagents.md b/build-queue/tasks/04-model-usage-subagents.md
new file mode 100644
index 0000000..6864c91
--- /dev/null
+++ b/build-queue/tasks/04-model-usage-subagents.md
@@ -0,0 +1,15 @@
+# AbramsEgo task 04 — model-usage + sub-agent-runs panel
+
+Read SPEC.md first. Add the command-center "Sessions & sub-agent runs" surface (panel 5).
+
+1. `server.js`: add an authed `GET /api/usage` collector that reads `~/.claude/cost-ledger.jsonl`
+   and returns model-usage breakdown (calls + tokens + $ per model, last 24h and all-time) and,
+   from `~/.claude/projects/**/*.jsonl` mtimes, a count of active/recent Claude sessions and recent
+   sub-agent runs (last 20, newest first). Fold a compact form into the main snapshot too.
+2. `public/index.html`: render a "Model Usage" mini-bar-chart (per-model share) and a "Recent
+   sub-agent runs" list. Each run row is an admin card → MUST show created date+time
+   (`🕓 …`, toLocaleString, full ISO in title=) per Steve's hard rule.
+3. Verify: `pm2 restart abramsego`, curl `/api/usage` returns non-empty, page renders the panel.
+   Commit `feat: model-usage + sub-agent-runs panel`.
+
+Local only. No deploy/keys/publish.
diff --git a/build-queue/tasks/05-git-activity-feed.md b/build-queue/tasks/05-git-activity-feed.md
new file mode 100644
index 0000000..ea1aa77
--- /dev/null
+++ b/build-queue/tasks/05-git-activity-feed.md
@@ -0,0 +1,14 @@
+# AbramsEgo task 05 — git activity feed across ~/Projects
+
+Read SPEC.md first. Build panel 6's git activity feed.
+
+1. `server.js`: add an authed `GET /api/activity` that scans the ~25 most-recently-modified
+   git repos under `~/Projects` and returns their latest 1-2 commits (repo, short hash, subject,
+   author-date ISO), merged and sorted newest-first, capped at 40 rows. Cache in the snapshot
+   with stale-while-revalidate (this shells out to git — keep it off the hot path).
+2. `public/index.html`: render an "Activity" feed. Each commit row is an admin card → show
+   the commit date+time per Steve's hard rule (🕓, toLocaleString, full ISO in title=).
+3. Verify: `pm2 restart abramsego`, curl `/api/activity` non-empty, feed renders newest-first.
+   Commit `feat: cross-repo git activity feed`.
+
+Local only. Read-only git (log/for-each-ref). No deploy/publish.
diff --git a/build-queue/tasks/06-hardrule-compliance-pass.md b/build-queue/tasks/06-hardrule-compliance-pass.md
new file mode 100644
index 0000000..fe6bd30
--- /dev/null
+++ b/build-queue/tasks/06-hardrule-compliance-pass.md
@@ -0,0 +1,18 @@
+# AbramsEgo task 06 — Steve hard-rule compliance pass on the dashboard
+
+Read SPEC.md first. Audit the LIVE dashboard (public/index.html + server.js) against Steve's
+hard UI rules and fix every gap. This is a compliance sweep, not new features.
+
+1. **Created date+time on EVERY admin card/tile/row** — fleet items, cron rows, sub-agent runs,
+   canary cards, wins, git rows. Format `🕓 Mon D, YYYY, h:mm AM` via
+   `toLocaleString(undefined,{year:'numeric',month:'short',day:'numeric',hour:'numeric',minute:'2-digit'})`,
+   visible on the card, full ISO timestamp in `title=`. Carry `created_at`/timestamp through each API.
+2. **Any grid/list of items** (sub-agent runs, activity, crons) → add a sort `<select>`
+   (Newest default + relevant modes) + a density `<input type=range>` controlling columns,
+   both persisted to localStorage; and infinite scroll (IntersectionObserver) if a list can exceed
+   ~40 rows. Coexist, don't conflict.
+3. **Costs** — confirm every paid-API figure is labeled; local/free reads show `$0 (local)`.
+4. Verify: `pm2 restart abramsego`, click through, confirm every card shows date+time and grids
+   have the controls. Commit `chore: hard-rule compliance (created date+time, sort+density, costs)`.
+
+Local only. No deploy/publish.
diff --git a/build-queue/tasks/99-replenish.md b/build-queue/tasks/99-replenish.md
new file mode 100644
index 0000000..1c38618
--- /dev/null
+++ b/build-queue/tasks/99-replenish.md
@@ -0,0 +1,17 @@
+# AbramsEgo task 99 — replenish the build queue (self-sustaining, BOUNDED)
+
+Read SPEC.md. This keeps AbramsEgo building non-stop toward the spec without a human.
+
+1. Compare the RUNNING dashboard (curl the :9773 APIs + read public/index.html + server.js)
+   against SPEC.md's 8 panels and Steve's hard rules.
+2. Identify the highest-value MISSING or incomplete items.
+3. Enqueue **at most 3** new task files into `build-queue/tasks/` (numbered above the current
+   max, e.g. 07/08/09), each a self-contained <15-min chunk written in the same style as tasks
+   01–06 (local-only, test against pm2 :9773, commit on success, gated work → drafts).
+   Then enqueue a fresh copy of THIS replenisher as the highest number so the cycle continues.
+4. **BOUND:** if the dashboard already satisfies SPEC (all 8 panels present + hard rules met),
+   enqueue NOTHING (and do not re-enqueue this replenisher) — let the loop rest. Non-stop until
+   done, not busywork forever.
+5. Commit any task files you add: `chore: replenish build queue (N tasks)`.
+
+Do NOT build features in this task — only audit + enqueue. Local only.
diff --git a/scripts/build-loop.sh b/scripts/build-loop.sh
index 61c453e..f2ee166 100755
--- a/scripts/build-loop.sh
+++ b/scripts/build-loop.sh
@@ -57,6 +57,13 @@ cat <(printf '%b' "$PREFIX") "$TASK" | RUN "$CLAUDE_BIN" --print --permission-mo
 rc=${PIPESTATUS[1]}
 if [ "$rc" -eq 0 ]; then
   mv "$TASK" "$Q/done/$name"; echo "[$(ts)] DONE $name -> $LOGF" | tee -a "$LOG"
+elif grep -qiE "hit your (usage|session) limit|session limit|usage limit|rate.?limit|resets [0-9]|overloaded|temporarily unavailable" "$LOGF"; then
+  # TRANSIENT rate-limit / model-unavailable — DO NOT burn the task. Leave it queued
+  # and rest cleanly (exit 0). launchd StartInterval re-kicks us; once the Max session
+  # limit resets the very same task drains untouched. Smart "always restart": never
+  # destroy work on a transient cap. (Root cause of the 2026-07-01 10:20 mass-fail.)
+  echo "[$(ts)] RATELIMIT $name — left in queue, clean rest; launchd heartbeat will retry -> $LOGF" | tee -a "$LOG"
+  exit 0
 else
   mv "$TASK" "$Q/failed/$name"; echo "[$(ts)] FAIL $name (rc=$rc) -> $LOGF" | tee -a "$LOG"
 fi

← dd646ce build-loop: portable perl-alarm timeout fallback (macOS lack  ·  back to AbramsEgo  ·  auto-save: 2026-07-01T10:41:35 (1 files) — build-queue/.loop 3534c2e →