--- name: smartbadge-ops description: 智能工牌录音管道全功能运维技能。当用户提到录音归档、录音下载、管道巡检、转录重试、每日录音任务、smartbadge 运维、归档失败、转录失败、录音清洗、讯飞转录、OSS 同步、分析任务状态、线上部署核验、健康检查、列表数据、故障自诊断、月报、年报、周报、日报汇总、报告解读、历史数据对比、区间数据聚合时使用。提供对服务器定时管道(归档→清洗→讯飞转录→DeepSeek 报告)的巡检、手动触发、补跑、重试、故障诊断、列表排查、月报/年报按需聚合分析、线上部署核验与浏览器走查。交互特色:先复述问题与方案,回问用户确认后再执行。 --- # 智能工牌录音管道运维(smartbadge-ops) 服务器(`server/index.js`)常驻运行每日定时管道,**无需人工值守**;本技能是控制面:巡检、诊断、补跑、重试、部署核验、区间(月报/年报)按需聚合分析。所有作业逻辑在服务器端,技能只调用其 REST API 与直连 OSS。 本技能为独立仓库,脚本全部在 `./scripts/`(零依赖,Node >=18;verify-online.py 需本机 playwright)。 --- ## §0 口径铁则(2026-09-17 林总裁钦定,最高优先,覆盖本技能其余章节) 历史工作**全部收尾完毕**。使用本技能只做一件事:**验证并汇报当前态能否正常使用**——巡检 12 项 PASS / 列表能出数 / 当日报告能产出 / 新录音转录管道在产出。 以下旧账一律**不查、不报、不修、不列为缺口、不当待办**: - 历史录音一百二十九条(八月末批次)零转录; - 本地数据库登记口径漂移(如仅某天有登记、早几天的记录查不到); - OSS 与本地数据库记录的数量差异、历史文件/清洗池问题; - fix_recordings.sh 等历史补跑脚本——**不执行、不催办、不提"给权限"**。 汇报模板只含四项:当前总量 / 当日数据 / 有无新问题 / 下一步建议。输出中出现指向旧账的"缺口/待办/历史遗留"字样即为违规。 --- ## §1 交互协议:确认门(第一优先,不可跳过) 无论用户请求什么,先走确认门: ### 重档(默认,适用于一切「有生产影响」或「参数不明确」的请求) - **写操作永远重档**:`archive/run`、`analysis/run`、`retry`、`retry-transcribe`、`repair-oss`、`config` PUT、任何 DELETE。 - 步骤: 1. **复述**:用 1-3 句话复述我理解的问题、时间窗、对象(哪些设备/日期)、期望产物(如「月报 Markdown」)。 2. **方案**:列出将执行的脚本与命令序列,并一句话说明**是否会写数据**。 3. **回问**:"是这个意思吗?" 等待用户确认(或纠正)。 - 用户纠正后:只用一句更新复述,再确认一次即执行,不重复长篇。 - 已确认动作链中的后续复查步骤(如补跑后复跑 `report-aggregate`/`reconcile` 归零验证)视为同一确认,无需再问。 ### 轻档(预授权:纯只读且参数齐全) 以下场景视为用户已授权,可`一句话备案`后直接执行(备案格式:`我将执行:…(若与预期不符请中断)`,不强制等待回答): - `get`/`list` 查询、`check-online.mjs` 巡检、`oss.mjs` 列举、`reconcile` 对账、`report-aggregate` 聚合、`fetch-report-text` 正文拉取、`verify-online.py` 走查。 - 用户说「巡检」「跑 check-online」等明确指令,直接执行。 ### 确认门例外 - 用户明确说「直接跑」「不用问」或已确认过相同模式请求 → 跳过回问,执行并在首句说明。 --- ## §2 连接与凭据 ```bash export MSYS_NO_PATHCONV=1 # 仅 Windows Git Bash 需要(防 / 开头参数被转成 Windows 路径);Linux/Docker 无此问题 ``` - **接口地址**:默认线上 `https://recording.sh-lami.com`;本地开发:环境变量 `SMARTBADGE_API_BASE=http://localhost:3002`(或各脚本 `--base`)。 - **登录**:`node scripts/api.mjs login <密码>`,token 缓存到 `scripts/.token`(各脚本自动共享)。 - **用户名/密码无内置默认值**(1.2.0 起零密钥原则):必须经环境变量或 `.env` 提供,缺省脚本报错提示;Docker 容器用 `-e SMARTBADGE_USERNAME=/PASSWORD=` 或 `--env-file` 注入。 - **凭据回退链**(OSS 等):`--env 参数` > `SMARTBADGE_ENV_FILE` > 技能仓库根 `.env`(npx 安装后复制 `.env.example` 填值) > 自动发现(向上扫本仓库同级/兄弟目录含 `server/.env` 的项目,如服务端项目与技能放在同一父目录) > 已存在的 `OSS_*` 进程环境变量。 - 敏感凭据只存在于服务端项目 `server/.env`(OSS/讯飞/DeepSeek/masterKey),本技能仓库**不含任何密钥**;`node scripts/oss.mjs --find-env` 可查看实际采用的 `server/.env` 路径。 - **平台**:技能本体零依赖 Node ≥18 跨平台(Windows/Linux/Docker 一致);`verify-online.py` 浏览器走查需要 playwright+chromium,容器/无浏览器环境跳过(用 `check-online.mjs` 替代);日期口径固定 Asia/Shanghai,容器 UTC 时区无需配置。 ## §3 能力矩阵与编排表 | 脚本 | 能力 | 典型参数 | |---|---|---| | `scripts/api.mjs` | 任意接口调用 | `login` / `get <路径>` / `post <路径> ''` / `env` / `--raw` / `--base` | | `scripts/check-online.mjs` | 12 项断言一键核查 | `[密码]` 或 `SMARTBADGE_PASSWORD` | | `scripts/verify-online.py` | 浏览器 5 页走查 + 0 错误断言 | 环境变量 `PLAYWRIGHT_BASE_URL/SMARTBADGE_*` | | `scripts/oss.mjs` | OSS 直连列举统计 | `[prefix]` `--json` `--env ` `--find-env` | | `scripts/report-aggregate.mjs` | **区间聚合(月报/年报/任意窗口)** | `--start --end [--type day\|week\|all] [--json] [--no-reconcile]` | | `scripts/fetch-report-text.mjs` | 报告正文拉取(HTML→文本) | `--id ` \| `--url <直链>` `[--preview] [--json]` | **用户需求 → 命令序列(编排参考)** - 「今天(这几天)管道有问题吗」→ `check-online.mjs` → 有 FAIL 走 §7 → 按 category 处置 → 汇总。 - 「昨天报告没有/转录失败」→ `api.mjs get /api/analysis/health` + `errors?pageSize=20` 看 category(§7 处置表)。 - 「昨天的数据/录音列表不对」→ §8 列表诊断。 - **「给我上月月报」(月报/年报 == 同流程换窗口)** → 确认门(窗口+产物形态)→ `report-aggregate --start 月初 --end 月末 --json` → 必要时补跑缺失日(§10)→ `fetch-report-text` 选 3-5 篇读正文 → 按 `templates/monthly-report.md` 八段模板产出 → 产物形态加工(Markdown/HTML/PPT)。 - 「上线后核验一下」→ §12(`check-online` + `verify-online.py` + `nginx -t` + `pm2 logs`)。 - 「OSS 里有哪些东西」→ `oss.mjs`(顶层)或 `oss.mjs recordings/` 等按前缀。 ## §4 架构与每日流程 ``` 每天 archive_time(默认 02:00 Asia/Shanghai, 可配 SbSystemConfig) ├─ 归档: 上游 /audio/list → 下载本地 → OSS(ETag 校验) → SbAudioRecording 落库(含音源字段镜像) ├─ 分析: process.py 三级过滤(静默/模糊/短音频) → 讯飞多说话人 → SbTranscriptSegment ├─ 报告: DeepSeek → HTML → reports/ + OSS → SbReport(day/week) ├─ 合并: 按设备×天拼接 MP3(OSS merges/,仅存档收听,不参与转录) ├─ 24h 清理: 已 OSS 同步文件 → canPurge → 删除本地(DB 记录保留) └─ 保留期兜底清理: 录音 15 天 / 合并 7 天 / 报告 HTML 7 天(删前补同步一次;报告 OSS 补传失败时安全闸保留本地) 每周一(archive_time+30min): 周报(近 7 天聚合, 转录增量跳过不重复计费) 失败任何环节 → 自动入队重试(3 次, 5/15/30 分钟指数退避) → 耗尽才进入错误展示;重试零残留 ``` **每日自诊断推送(2026-09-08 起 v2)**: cron `aa6127c5c572` 每天 08:00(北京) 运行 `/opt/data/scripts/smart_daily_push.py`(零 LLM token, no_agent): ① 有日报 → 下载→发布个人存储 `https://s3.fmode.cn/user/QJ0z4hZJij/report/smartbadge/smart-report-.html` → 发拉迷群(对外统一个人存储链接, **不给 OSS 直链**) ② 无日报 → **自诊断**:分析任务合并视图(采集/静默/转录/损坏计数) + 错误分类 + 健康度: - 有效录音>0 但报告失败 → **自动补跑** `analysis/run`(转录增量不重复计费) → 推送(标注"自动补跑") - 有效人声 0 段 → **自动发情况说明到群**(含采集/静默/损坏数字, marker 幂等防重发) - 管道 running/重试中 → 等 2 分钟复查, 仍无果 [ALERT] 不发群(防误报) - quota 额度受限 → 群说明 + [ALERT]; 管道没跑/无任务记录 → [ALERT] ③ 全程运维日志 `/opt/data/voc/data/smartbadge_push_log.jsonl` 发布依赖 venv `/opt/data/.venvs/pub`(esdk-obs-python; 失效重建: uv venv + uv pip install esdk-obs-python)。 **边界事实(设计依据)**: - 归档窗口 ≤7 天(上游自动删除录音)→ 错过即丢;>`6` 天前的缺失**不可补**。 - `POST /api/analysis/run` 窗口上限 `MAX_WINDOW_DAYS=7`、start 晚于今天报错、全局互斥 1 个任务(冲突 429)→ 区间聚合/补跑严格遵守:一次最多 7 天,或逐日。 - 录音列表默认本地库(截至昨日);`endDate >= 今天` 走上游实时分流。 - 转录消耗讯飞额度(每文件一次;清洗已滤约 90% 无效音频;周报/聚合复用已转录段落不重复计费)。 ## §5 接口命令速查(经 api.mjs) | 命令 | 用途 | |---|---| | `get /api/archive/status?date=&deviceNo=` | 当日归档状态(expected/downloaded/ossSynced/failed) | | `get /api/archive/missing` | 归档失败待重试列表(含 retryCount/lastError) | | `post /api/archive/run '{"dates":[...]}' \| '{"dateRange":{"start","end"}}' \| '{"devices":[...]}'` | 手动触发归档(默认全部×昨天) | | `post /api/archive/retry '{"ids":[...]}'` | 重试失败归档(也支持 {date}/{deviceNo}) | | `post /api/archive/retry-transcribe '{"date":"YYYY-MM-DD"}'` | 仅重跑转录(不重复清洗;互斥 429) | | `post /api/analysis/run '{"period":"yesterday"\|"last7days"\|{"start","end"},"type":"day"\|"week"}'` | 手动分析(窗口≤7 天,互斥) | | `get /api/analysis/jobs?status=&page=&pageSize=` | 任务列表(status/progress/summary/reportId/transcriptCount/nextRetryAt/failStage) | | `get /api/analysis/reconcile?date=` | 三方对账(total/localHit/ossHit/transcribeDone/missingCleansed/missingTranscript) | | `post /api/analysis/repair-oss '{"date":"YYYY-MM-DD"}'` | 补传缺失 OSS 对象(互斥 429;支持 {ids}) | | `get /api/analysis/health` | 健康快照(retryingCount/warnings/categoryCounts/ossMissingCount) | | `get "/api/analysis/errors?pageSize=20"` | 错误汇总(四来源,含 advice;重试中默认隐藏,`includeRetrying=true` 查) | | `post /api/smartbadge/recordings/list '{"page":1,"pageSize":20}'` | 录音列表(本地库;支持 deviceNo/startDate/endDate/keyword;endDate>=今天走实时) | | `post /api/smartbadge/logs/heartbeat '{"page":1,"pageSize":20}'` | 心跳列表(startTime/endTime 代替日期) | | `get /api/devices?page=&pageSize=&keyword=` | 设备分页(DB 级) | | `get /api/config` / `put /api/config '{"key":"value"}'` | 系统配置(archive_time 等;**PUT 前必过确认门**) | | `get /api/reports?type=day\|week&start=&end=&pageSize=` | 报告列表(分页;无正文) | | `get /api/reports/:id` | 报告详情(同样无正文;正文经 ossUrl/downloadUrl) | > 写请求必须带 `X-Requested-With` 头——api.mjs 已自动带上;手动 curl 时须加。 ## §6 每日巡检 SOP(营业前一次) 1. `node scripts/check-online.mjs` → **12 项全 PASS 即健康**;0 FAIL 跳第 5 步汇报。 2. 有 FAIL:进 §7 定位——先 `api.mjs get /api/analysis/health` 看 `retryingCount`(>0=引擎自动重试中,别急)。 3. `api.mjs get /api/analysis/reconcile?date=<昨天>` 核对缺项;`oss.mjs` 核对四类目录数量(`recordings/ cleansed/ transcripts/ reports/`)。 4. `<昨天>` 有 `missingCleansed`/`missingTranscript` → `repair-oss '{"date":"<昨天>"}'` 补传,复跑验证归零。 5. 三行简报:正常项 / 异常项(及原因分类)/ 采取的动作。 6. 周一额外:`jobs?pageSize=5` 见 week 任务 + `get /api/reports?type=week` 有周报。 ## §7 故障自诊断 SOP ```bash node scripts/api.mjs get /api/analysis/health # retryingCount=自动重试中数;categoryCounts=分类计数 node scripts/api.mjs get "/api/analysis/errors?pageSize=20" # 重试中项默认隐藏(耗尽才出现) node scripts/api.mjs get "/api/analysis/errors?includeRetrying=true&pageSize=20" ``` > **重试语义**:失败先自动重试 3 次(5/15/30min,~50 分钟),耗尽才可见。`retryingCount>0` → 等引擎;0 且有 warnings → 真错误。 > **无害告警**:health `warnings` 中「最近任务无待转录文件(属正常)」是无害告警(当日无录音或全部被三级过滤),不影响健康判定;check-online 已按此语义断言。 按返回 `category` 行动(每条自带 `advice`): | category | 含义与动作 | |---|---| | `quota`(额度/并发) | 讯飞/DeepSeek 额度受限或并发超限(10407/10901/402/429/rate limit):**非接口故障**,等恢复或联系开通;可稍后 `retry-transcribe`/`analysis/run`(增量跳过,成本低) | | `network`/`timeout` | 网络抖动/超时(ETIMEDOUT/ECONNREFUSED/socket):**重试即可**;当日重试 `archive/retry`/`retry-transcribe` | | `auth`(鉴权) | 密钥/令牌错误(401/403/accessKeyId/signature):**报修**——检查服务器 `server/.env` 的 OSS_*/IFLYTEK_*/DEEPSEEK_API_KEY 是否过期,修复后重试 | | `server`(5xx) | 上游 5xx 或内部错误:**报修**——查 `pm2 logs smartbadge-api` 或宝塔日志 | | `other` | 未知格式:人工看 `message`;可复现则升级分类器关键词 | **口径示例**:「今天的报告为什么没有?」→ `errors?source=report` → quota:「不是接口问题,额度受限,已自动重试,等待恢复」;auth:「鉴权失败,需检查密钥(报修项)」。**先跑命令看 category,不要凭猜回复。** ## §8 列表问题诊断 SOP 1. 本地列表(默认窗)`recordings/list` → total>0 且无 failed/capped?缺失日 = 归档失败日:查 `archive/status?date=` 与 `archive/missing`。 2. 「包含今日」开关走实时——`failed`/`capped` 非空 = 上游个别设备失败/超 2000 条截断;等 60s 缓存或缩小筛选。 3. `startTime` 全为 `-`:上游 `/audio/list` 最后一条元数据未结算(数据源属性);旧行缺字段可跑回填脚本 `server/scripts/maintenance/backfill-recording-meta.js`。 4. 上游误返全量:服务端已有近 7 天缺省窗,**勿**移除。 ## §9 补跑与重试 SOP - 昨天断电/失败 → `post /api/archive/run '{"dates":["<昨天>"]}'`(仅收 今天-6 ~ 今天)。 - 部分文件下载失败 → `post /api/archive/retry '{}'`(按日期/设备过滤更精准)。 - 转录失败 → `post /api/archive/retry-transcribe '{"date":"<日期>"}'`。 - 报告失败(任务 error 含「报告生成失败」)→ `post /api/analysis/run '{"period":"yesterday","type":"day"}'`(已转录增量跳过,只补报告)。 - 互斥 429 → 已有任务运行中:先 `get /api/analysis/jobs` 看进度;分析有超时兜底(20 分钟),等待即可。 - **跨 >6 天窗口的缺失:上游已删,不可补**,在汇报中披露。 ## §10 月报/年报 SOP(按需聚合,不建永久管道) 系统仅自动产生 day/week 报告;月报/年报 = **运行时拉取窗口数据自动聚合分析**。执行步骤: 1. **确认门(重档无关,但必须问)**: - 窗口:如「2026 年 8 月」= `--start 2026-08-01 --end 2026-08-31`;年报同理 `01-01 ~ 12-31`;或自定义区间。 - 内容范围:仅数据(录音/转录/报告清单)还是含智能分析(读报告正文提炼)?默认含。 - **产物形态**由用户选择:① Markdown(默认,回复正文+可存文件)② HTML(模板 `templates/report-html.html` + markdown 最小转换)③ PPT(使用全局 weekly-report-pptx 技能承接)。 2. **拉数据**:`node scripts/report-aggregate.mjs --start <起> --end <止> --json`(可 `--type week` 只看周报;`--deviceNo` 单设备;`--no-reconcile` 跳过逐日对账)。得到:报告清单、逐日明细、**缺失三类清单(无报告日/转录=0 日/对账异常日)**、补跑建议命令。 3. **补缺失(过确认门)**:对 `daysAgo<=6` 的无报告日,执行聚合输出里的建议命令(逐日 `analysis/run`,`{"period":{"start":D,"end":D},"type":"day"}`);复跑聚合验证归零。 4. **读正文(需要智能分析时)**:`node scripts/fetch-report-text.mjs --id --preview` 选 3-5 篇代表性报告(readme 说选择标准:设备覆盖广、转录量高、异常日),必要时 `--json` 定位 id(或 `api.mjs get "/api/reports?type=day&start=<起>&end=<止>&pageSize=10"`)。 5. **产出**:按 `templates/monthly-report.md` 八段(总体概览/设备活跃/录音量与转录效率/趋势/异常与缺失/报告要点摘录/结论与建议)成稿;形态按第 1 步选择。 6. **披露**:超 6 天的缺失日标注「上游已清理,不可补」;`summary=「无待转录文件」` 的任务属正常(三级过滤)。 **注意**:`report-aggregate` 是只读(轻档权限);「补缺失」是写操作,必须重档确认。 ## §11 报告解读 - 列表/详情无正文:正文经 `ossUrl`(OSS 公开直链)或 `downloadUrl`(302 OSS / 本地回源)获取 → 推荐 `fetch-report-text.mjs`。 - 阅读视角(KPI 指标卡、客户画像表、关键事件时间线、销售策略、VOC 原话、风险提示);报告只含转录文本与指标,不内嵌录音 URL。 - 报告 HTML 是 DeepSeek 提炼物(含 VOC 引用 6-9 条),非全文转录;需要全文 → §13。 ## §12 上线/部署核验 SOP ```bash node scripts/check-online.mjs # 12 项断言: 登录/health/归档/列表/实时分流/心跳/设备/互斥 python scripts/verify-online.py # 浏览器: 5 页走查 + 0 pageerror 断言 nginx -t # 宝塔保存自动校验;配置见 deploy/nginx-recording.sh-lami.com.conf pm2 logs smartbadge-api --lines 50 # 服务器错误日志 ``` - 前端打包:项目内 `pnpm build` → zip 上传解压到线上 dist;后端 `.env` 用 `.env.production` 模板(PORT=3007)+ CDN 自动拉取。 - **双进程提醒**:共享 Parse 只允许一个后端常驻跑 cron——本地(3002)与线上(3007)不要同时在线。 ## §13 转录原文获取(边界) - 转录原文**无 HTTP 接口**,数据在 Parse `SbTranscriptSegment`(CLP 仅 masterKey,技能侧不可直读)。 - OSS 有转录文本对象:`transcripts/{deviceNo}/{Y}/{M}/{D}/*.txt` → `node scripts/oss.mjs transcripts/` 列举,经 `publicDomain` 拼直链可下载。 - 需逐条查原文时,在企业内用服务器 masterKey 侧(如维护脚本),不在本技能承诺。 ## §14 注意事项 1. **归档窗口 ≤7 天**:错过即丢,巡检每天执行。 2. 写操作(归档/分析/重试/补传/配置)一律先确认门,并提示互斥 429 可能性。 3. 凭据只存 `server/.env`(讯飞/DeepSeek/OSS/masterKey),本仓库零密钥;git 提交需用户明确同意。 4. **禁止直接在 `server/recordings/` 下手动跑 `process.py`**:对输入文件是**移动/删除**语义;排查过滤请用工作区副本或 `repair-oss`。 5. Python 仅服务器端管道需要;技能本体不调 Python(**Docker/Linux 容器零 Python 依赖可跑全部 Node 脚本**)。唯一例外 `verify-online.py`(浏览器走查)需在宿主机执行 `pip install playwright && playwright install chromium`。 6. `.token`/`out/`/`__pycache__` 已 gitignore,不提交。 ## §15 结束协议(每任务收尾) 输出三行:① 做了什么(命令序列)② 结果(数据或 PASS/FAIL + 异常项)③ 遗留与建议下一步。有「未验证项/已知限制」要显式披露。 ## 相关技能 - 报告人工解读模板细节见项目内 `smartbadge-report`(执行报告解读时可调用)。 - PPT 产物:全局 `weekly-report-pptx` 技能。