周度制作者数据资产复盘
/ops/funnel-review 是一张浏览器本地的看板,把一周的制作活动
—— 构建尝试、三元组沉淀、硬件覆盖、espctl 工具使用 —— 渲染出
来,并生成一份 Markdown 工作周报,可以直接粘贴到博客、群聊或邮件。
整页不联网。它从 localStorage 里读一份 JSON 快照,其余都从这份
快照计算出来。清浏览器缓存,快照丢失。
数据流
+--------------------+ 通过 +-----------------------+
| 本地 espctl / | chrome-mcp | window.aegis |
| chrome-mcp / | evaluate_ | .importMakerStats() |
| playwright-mcp | script 推 | |
+--------------------+ ───────────► +-----------+-----------+
|
v
localStorage:
aegis.maker-stats.snapshot
|
v
/ops/funnel-review 挂载时读,
也监听 aegis:maker-stats:updated
事件实时刷新。
三种方式可以写入快照:
- 浏览器驱动型 MCP agent(推荐)。chrome-mcp 或 playwright-mcp
打开
https://esphome.cloud/ops/funnel-review(或本地 dev URL), 用evaluate_script调window.aegis.importMakerStats(snapshot)。 - 手工粘贴。打开
/ops/settings,在「制作者数据资产 · 导入」 一栏粘贴 JSON 快照,点导入。 - 直接写 localStorage。任何能写
localStorage.aegis.maker-stats.snapshot的浏览器工具都行;页面 通过storage事件自动刷新。
没有服务器端摄取。同一台机器两个浏览器看到的快照不同 —— 各自的
localStorage 互相隔离。
localStorage 是缓存,不是源数据。 这是设计取舍。源数据在
~/maker-assets/{public,private,asset}/triples/,由espctl deposit写入。浏览器里的快照只是 agent 推进来的派生视图。 清浏览器缓存、换浏览器、换设备,丢的都是视图,不是资产。 要恢复视图:重新跑espctl deposit list --since/--until --json, 聚合,再调一次window.aegis.importMakerStats(...)。
Agent 维护合同 —— 每次访问都刷新
这是 agent 在浏览器 tab 里导航到任何 /ops/* URL 时应该走的协议。
默认假设 localStorage 刚被清过,不要以为昨天的快照还在或还新。
- 打开 tab 之前(或刚
navigate_page之后),agent 在用户机器 上跑espctl deposit list --since <本周一> --until <今天> --json, 把结果连同它自己的工具调用计数聚合成新的MakerStatsSnapshot。 - 在 tab 里,agent 通过
evaluate_script调window.aegis.importMakerStats(snapshot)。 - 校验页面对
aegis:maker-stats:updated有响应 —— DOM 里的 快照块(或window.aegis.getMakerStats())反映出新 push 的generatedAt时间戳。
为什么每次都推,而不是每周一次:
- 浏览器在存储压力下可能驱逐 localStorage(默认 quota 非 persistent)。
- 用户两次访问之间可能清过站点数据。
- 用户可能在另一个浏览器、隐身窗口、或另一台机器上打开 tab。
- 制作者从上次 push 之后可能跑了新构建;陈旧视图比没视图更糟。
一个行为正确的 agent 把 /ops/* 当成 到达即渲染 处理 —— 不
依赖任何前次会话的状态。push 成本很低(一次 evaluate_script 带
一个 JSON object);多 push 也无害,因为校验器会丢非法快照,
aegis:maker-stats:updated 也只在写入成功后才派发。
快照 schema
interface MakerStatsSnapshot {
generatedAt: string; // ISO 时间戳,本快照的生成时刻
windowStart: string; // ISO,统计周的第一天
windowEnd: string; // ISO,统计周的最后一天
buildAttempts: number;
buildSuccesses: number;
triplesDeposited: number;
hardwareMix: Array<{
platform: string; // 如 'esp32-s3'、'stm32g4'
attempts: number;
successes: number;
}>;
topEspctlTools: Array<{
tool: string; // 如 'espctl.build'、'espctl.deposit.add'
count: number;
}>;
notes?: string; // agent 留的自由文本
}
importMakerStats 严格校验:
- 所有计数必须是有限非负数。
platform和tool必须是非空字符串。- 未知字段静默丢弃;必填字段缺失会返回
{ ok: false, error: 'schema mismatch — ...' }。
浏览器 API 合同
页面在 window.aegis 下挂了三个函数,由
src/lib/user-settings/maker-stats.ts 里的
installMakerStatsWindowApi 在任意路由挂载时装好:
| 函数 | 返回 | 说明 |
|---|---|---|
window.aegis.importMakerStats(jsonOrObject) | { ok: boolean, error?, snapshot? } | 接受 JSON 字符串或已解析对象。持久化 + 派发 aegis:maker-stats:updated。 |
window.aegis.getMakerStats() | MakerStatsSnapshot | null | 读当前快照,无则 null。 |
window.aegis.clearMakerStats() | void | 移除快照,页面回到空态。 |
监听快照变化:
window.addEventListener('aegis:maker-stats:updated', (event) => {
console.log('new snapshot', event.detail);
});
从 espctl 产出快照
目前还没有一等公民的 espctl stats --json 命令。落地之前,在
agent 里自己聚合。最小化配方:
# 数本周三元组台账里的构建结果
espctl deposit list --since 2026-05-17 --until 2026-05-24 --json > week.json
espctl skills --format json > skills.json
浏览器驱动型 agent 把这两份合成快照然后推:
// agent 在收集到上面 JSON 后跑的伪代码
const snapshot = aggregate(weekJson, skillsJson);
const result = await chromeMcp.evaluateScript(
`window.aegis.importMakerStats(${JSON.stringify(snapshot)})`,
);
if (!result.ok) throw new Error(result.error);
/ops/funnel-review 推算出什么
载入快照后页面计算:
- 6 张数字卡 —— 构建尝试、成功(附成功率)、三元组(附沉淀率)、 硬件平台数、espctl 工具种类、总调用数。
- 硬件分布柱图 —— 每个平台两根柱(尝试 vs 成功)。
- espctl 工具 top 横向柱图 ——
topEspctlTools里上报的工具 按频度排。 - 5 条判断检查 —— 构建活跃度、成功率、三元组沉淀率、硬件多样
性、工具栈深度,每条
健康/观察/需关注。 - 1 个总判断 badge ——
继续推进/需要观察/需要回滚 / 处理,取 5 条检查里最差那条。 - Markdown 工作周报 —— 一份可直接粘贴的摘要,含制作者名、
窗口、构建数、硬件分布、top 工具、
notes备注。点复制 Markdown 按钮直接写到剪贴板。
空态
快照缺失或解析失败时,页面渲染一个简短的空态,带跳转
/ops/settings 的按钮让你手工粘一份。空态和有快照的态布局不共用 ——
页面要么渲染前者要么后者,二者择一。
相关
espctl deposit—— 三元 组计数的源头。- CLI 实用工具 —— 从 agent shell out
时会用的
--json/--quiet全局标志。 - 工具索引 —— 所有可能出现在
topEspctlTools里的espctl子命令。