Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Weekly Maker Asset Review

The /ops/funnel-review page is a browser-local dashboard that renders one week of maker activity — build attempts, triple deposits, hardware coverage, and espctl tool usage — and emits a Markdown work-report you can paste into a blog post, a group chat, or an email.

The page never talks to a server. It reads a single JSON snapshot out of localStorage and computes everything else from there. Clearing your browser storage clears the snapshot.


Data flow

+-------------------+      pushed via       +----------------------+
| local espctl /    | -- chrome-mcp -->     | window.aegis         |
| chrome-mcp /      |    evaluate_script    |   .importMakerStats()|
| playwright-mcp    |                       |                      |
+-------------------+                       +----------+-----------+
                                                       |
                                                       v
                                            localStorage:
                                            aegis.maker-stats.snapshot
                                                       |
                                                       v
                                            /ops/funnel-review reads it
                                            on mount and on the
                                            `aegis:maker-stats:updated`
                                            event.

Three ways to populate the snapshot:

  1. Browser-driving MCP agent (recommended). chrome-mcp or playwright-mcp opens https://esphome.cloud/ops/funnel-review (or your local dev URL) and calls window.aegis.importMakerStats(snapshot) via evaluate_script.
  2. Manual paste. Open /ops/settings, paste a JSON snapshot in the Maker Data Asset · Import section, click Import.
  3. Direct localStorage write. Any browser tool that can write localStorage.aegis.maker-stats.snapshot works; the page picks up the change via the storage event.

There is no server-side ingestion. Two browsers on the same machine see different snapshots because they each have their own localStorage.

localStorage is a cache, not the source of truth. This is by design. The source of truth lives in ~/maker-assets/{public,private,asset}/triples/ — the ledger that espctl deposit writes. The browser-side snapshot is just a derived view that an agent pushes in. Clearing the browser cache, switching browsers, or hopping devices all lose the view, never the asset. To restore the view: re-run espctl deposit list --since/--until --json, aggregate, and call window.aegis.importMakerStats(...) again.

Agent maintenance contract — refresh on every visit

This is the protocol an agent should follow whenever it navigates a browser tab to any /ops/* URL on this site. Treat localStorage as if it were just cleared; don’t assume yesterday’s snapshot is still there or still current.

  1. Before opening the tab (or right after navigate_page), the agent runs espctl deposit list --since <start of current week> --until <today> --json on the user’s machine and aggregates the resulting triples (plus its own tool-call counts) into a fresh MakerStatsSnapshot.
  2. Inside the tab, the agent calls window.aegis.importMakerStats(snapshot) via evaluate_script.
  3. Verify the page reacted to aegis:maker-stats:updated — check that the snapshot block in the DOM (or window.aegis.getMakerStats()) reflects the freshly pushed generatedAt timestamp.

Why every visit, not just once a week:

  • The browser may have evicted localStorage under storage pressure (default quota is not persistent unless requested).
  • The user may have cleared site data between visits.
  • The user may have opened the tab in a different browser, an incognito window, or on a different machine.
  • The maker may have run new builds since the last push; a stale view is worse than no view.

A correctly-behaving agent treats /ops/* as render-on-arrival — it does not assume any state from a previous session. The push is cheap (single evaluate_script with a JSON object); pushing unnecessarily is harmless because the validator drops invalid snapshots and dispatches aegis:maker-stats:updated only on successful writes.


Snapshot schema

interface MakerStatsSnapshot {
  generatedAt: string;     // ISO timestamp, when this snapshot was produced
  windowStart: string;     // ISO; first day of the week being summarized
  windowEnd: string;       // ISO; last day of the week being summarized
  buildAttempts: number;
  buildSuccesses: number;
  triplesDeposited: number;
  hardwareMix: Array<{
    platform: string;      // e.g. 'esp32-s3', 'stm32g4'
    attempts: number;
    successes: number;
  }>;
  topEspctlTools: Array<{
    tool: string;          // e.g. 'espctl.build', 'espctl.deposit.add'
    count: number;
  }>;
  notes?: string;          // free text from the agent
}

importMakerStats validates strict types:

  • All counts must be finite non-negative numbers.
  • platform and tool must be non-empty strings.
  • Unknown keys are dropped silently; missing required keys reject with { ok: false, error: 'schema mismatch — ...' }.

Browser API contract

The page exposes three functions on window.aegis. They are installed once when any route mounts (via installMakerStatsWindowApi in src/lib/user-settings/maker-stats.ts):

FunctionReturnsNotes
window.aegis.importMakerStats(jsonOrObject){ ok: boolean, error?, snapshot? }Accepts a JSON string or a parsed object. Persists + dispatches aegis:maker-stats:updated.
window.aegis.getMakerStats()MakerStatsSnapshot | nullReads the current snapshot, or null if none.
window.aegis.clearMakerStats()voidRemoves the snapshot. The page swaps back to the empty state.

Listen for snapshot changes with:

window.addEventListener('aegis:maker-stats:updated', (event) => {
  console.log('new snapshot', event.detail);
});

Producing a snapshot from espctl

There is no first-party espctl stats --json command yet. Until that lands, build the snapshot in your agent. A minimal recipe:

# count this week's builds + outcomes from the local triple ledger
espctl deposit list --since 2026-05-17 --until 2026-05-24 --json > week.json
espctl skills --format json > skills.json

A browser-driving agent can then aggregate these into a snapshot and push it:

// pseudocode the agent runs after collecting the JSON above
const snapshot = aggregate(weekJson, skillsJson);
const result = await chromeMcp.evaluateScript(
  `window.aegis.importMakerStats(${JSON.stringify(snapshot)})`,
);
if (!result.ok) throw new Error(result.error);

What /ops/funnel-review derives

Once a snapshot is loaded the page computes:

  1. Six numeric tiles — build attempts, successes (with pass rate hint), triples (with yield hint), hardware platform count, espctl tool variety, total tool calls.
  2. Hardware mix bar chart — per-platform attempts vs successes.
  3. Top espctl tools bar chart — horizontal frequency chart of the tools reported in topEspctlTools.
  4. Five decision checks — build activity, pass rate, triple yield, hardware diversity, tool depth. Each is pass / watch / attention.
  5. One overall badgeKeep going / Watch / Roll back / handle, derived from the worst of the five checks.
  6. Markdown work report — a copy-pasteable summary with maker name, window, builds, hardware breakdown, top tools, and the optional notes field. The Copy Markdown button writes it to the clipboard.

Empty state

If the snapshot is missing or fails to parse, the page renders a short empty-state with a link to /ops/settings so you can paste one manually. The empty state and the populated state share no layout — the page either renders one or the other in full.


  • espctl deposit — where the triple counts come from.
  • CLI Utilities — the --json / --quiet global flags you’ll use when shelling out from an agent.
  • Tool Index — every espctl subcommand you might want to count in topEspctlTools.