PackHorizon
AI 包装设计决策平台,让品牌方上传产品 → AI 诊断 + 优化方向 + 概念图 + Brief。
packhorizon.mvp.restry.cn。
2026-05-09 第一次 QA 端到端测试(4 项中 3 真修 1 误报,fries)
外部 QA 跑了一轮端到端,提了 7 条;fries 当场分类——P0/P1 真修 4 条、P2 体验 1 条、其余 2 条假阳性。派 1 个 CC 串修,部署后 QA 复测:
| 编号 | 报告症状 | 判定 | 处置 |
|---|---|---|---|
| Q1 | ”使用这个方向”按钮 CDP 超时 / 100% 必现 | 旧 bundle bug(即 R23 那个 o.startsWith 已在 2efb67a 修) | 新 bundle 部署后复测 PASS |
| Q2 | 首页 nav /#advantages /#workflow /#pricing 点了空白 | 误报——CC 实测 + fries vision 复核:scrollY 1264 / 2238 / 3832 各档卡正常显示 | 不动;让 QA 用最新页面复测 |
| Q3 | /app/profile 安全设置 / 通知偏好 / 导出偏好 标签按钮高亮但内容不切 | 真问题,client state 没接 | 接通 + 其余 3 个 tab 显式标”即将上线” |
| Q4 | 详情页滚动中段空白 | 误报——空 project 的”待生成”placeholder | 不动 |
| Q5 | ”先在上方完成新建项目的引导,再开始对话”提示模糊 | 真问题,P2 文案 | 改为”先左上方点击【新建项目】开完引导,再开始对话” |
经验:外部 QA 报告先验证再改,警惕”页面空白""崩溃”这类描述被当成真 bug;R23 那种已修 bug 在旧 bundle 里仍然能复现,复测前先确认 bundle 哈希。Q2 这次给 QA 回信时附了 fries 的截图证据,避免来回扯皮。
概述
2026-04-27 在 fries-mac 端起项的 bochub-style 新项目(不上 monorepo / 不要 docker-compose)。Claude Code (claude-opus-4-7 --effort medium) 跑 scaffold —— opus-4.7 上游只接受 medium,high/low → 400。04-28 一日完成 R10–R15 六轮硬化(concept watchdog / Lightbox / 维度评分 / 首页 session / 死链 / admin /_a/ 隐藏)。
技术栈
| 项 | 值 |
|---|---|
| 仓库 | Restry/PackHorizon |
| 路径 | ~/projects/PackHorizon |
| 框架 | Next.js 15 App Router + TS + Tailwind v4(shadcn 强制 v4)+ shadcn/ui |
| 包管理 | npm + --no-src-dir,dev 端口 3010,prod 端口 3793 |
| ORM | Prisma 6(13 张表) |
| 域名 | packhorizon.mvp.restry.cn |
| AI | Azure OpenAI Sweden v1(chat=gpt-5.4 + vision、image=gpt-image-1.5 快 / gpt-image-2 高质量,admin 后台热切) |
| DB(dev) | postgresql://admin:Nexora%40PG2026@192.168.1.235:15432/packhorizon_dev |
| DB(prod) | deployer 共享 PG,db packhorizon,owner image_studio |
| 登录 | 走 wx-gateway(公众号「造悟者」AppID wx225bf76b06064faa,Token phToken_x9k2vP4qLm) |
| WX 白名单 | mvp-deployer 出口 163.228.243.161 |
| Admin 路径 | /_a/ad7c3ec948e19de4bd13dc696d63cf85(32-hex slug,env ADMIN_PUBLIC_PATH,仿 _next/) |
业务流程
[微信扫码登录] → [新建项目: 上传图 + 表单] → [诊断 30 积分: GPT-5.4+Vision 打分+6维度]
→ [优化方向 20 积分: 2-3 差异化方向] → [概念图 50 积分: gpt-image-1.5/2 出图]
→ [Brief: 设计需求+信息层级+配色+印刷参数]
→ 出口 A: 自交付(拿 Brief 自己找设计师)
→ 出口 B: 服务订单(定制报价 → 设计师落地 → 印刷文件)
返工路径:对概念图不满 → 重出同方向(再扣 50)/ 换方向(继续走流程)。
R0(04-27)— 微信扫码登录从 0 到通
- PG 库
packhorizon在 deployer host PG 16 建好(image_studio用户即 owner);DSN 写~/.credentials/.env的PACKHORIZON__DATABASE_URL,部署时自动注入 - 微信公众号 IP 白名单加 deployer 出口
163.228.243.161—— 之前40164的根因 - 服务器配置(明文模式 + Token + EncodingAESKey)提交时微信 GET
/api/wx/callback?echostr=...验证;通过后**还要点”启用”**才生效 - 真正卡几小时的 bug 是 wx-gateway
parseXml正则贪婪:所有微信推送的事件被静默丢弃,selftest 还 PASS 把人误导。修完伪造 SCAN POST 立即 token=confirmed - 第一次跳成功但跳到
https://localhost:3793/app——req.nextUrl.clone()拿到反代上游内部 host,需用x-forwarded-host/-proto重建(沉淀 skillnextjs-reverse-proxy-redirect-leak)
⚠️ 排查时用户看到的「公众号不可用」字样是公众号会话框未配自动回复,跟登录无关。判断登录是否成功只看:浏览器
/login是否跳/app。
M1(04-27)— 营销页 + 登录页 1:1 复刻(commit 345c39c)
/、/pricing 1:1 复刻原型 frontend.html(4 section + 三档价格卡 + Hero 渐变标题),登录页改造适配 wx-gateway。
browser-agent 桌面端验证盲区:CC 用的 browser-agent 操作真 Chrome 窗口,没法程序化改 viewport 宽度 —— 它报告的”桌面端 4 张截图”实际全是 360px 移动布局,等于桌面布局根本没验证。后续 Hermes 自己用 headless Chrome 1440 复核才算数(已记 memory 铁律)。
R1–R9(04-27)— 加固 9 commit(约 36 个产线问题)
f24bf4c…ec4cf79:
| 类别 | 内容 |
|---|---|
| DB-backed 速率限制 | RateLimitAttempt 表(sliding window),替代内存计数 |
| 资产访问审计 | AssetAccessLog,admin 跨用户读资产留痕 |
| WxFinalizeLog 删除 | PC 扫码走 openid + OAuth refill 两次 finalize 是设计内行为,不应误判重复 |
| 假充值闸门 | paid:true 写入前必须 admin 审核通过事务幂等 |
| 文件代理强制 auth | 直链泄漏防御 |
| admin step-up | ?case= 签名校验,敏感对象短期 step-up token |
图片 URL 308 跳 localhost:3794 | 服务端拼绝对 URL 用 req.url,反代后取内部 host → 改 publicBase(req) 读 x-forwarded-host/-proto |
| 管理员 OAuth callback 401/307 死循环 | mode 从 DB 读改成 request cookie 判别 |
R8 用户 shell(45ce053)删硬编码占位,/api/auth/me 真实 name/avatar/credits。
R9 wx-gateway 协议对齐(d9870b8):HMAC 4 字段 token|openid|unionid|ts、删 WxFinalizeLog 防重放(二次 finalize 是设计内行为)、finalize 改纯幂等 upsert 不覆盖用户已编辑 name、UA 检测微信内浏览器跳 OAuth。
R9.1 2949335 avatarUrl 字段名兼容(sp.get("avatarUrl") ?? sp.get("avatar"))。
R9.2 ec4cf79 mode 判定改 req.cookies.get(SESSION_COOKIE) —— 旧逻辑 DB 有 session → 误判 refill → 不下发 cookie → 死循环。
R10(04-28,commit d02bcbb)— concept 超时 + watchdog + 模型切换
线上有概念图 12h+ 卡 pending,根因 Azure gpt-image-2 默认 SDK timeout 太短(60-120s 大图常超)。修:
- 超时 10min:
getAzureClient()加timeout: 600_000,route.ts加maxDuration=600+runtime=nodejs - pending watchdog:
/api/cron/concept-watchdog每 5min 扫status=pending && createdAt < now-10min→ 刷 failed + 退积分(idempotencyKey 防双退) - 模型切换:admin
/admin/models加单选gpt-image-1.5/gpt-image-2,DB SystemSetting 单例,不改 env 不 redeploy 即可切 - 修旧账:
scripts/fix-stuck-concepts.mjsswept=2 refunded=2
verify 5/5 PASS,watchdog 自动回收线上 1 条 stuck(swept=1 refunded=1)。Cron 装上 */5 * * * *。
R11(04-28,commit b396c53 + e960e64)— Lightbox + 维度评分
| Bug | 真因 + 修法 |
|---|---|
| 维度评分”格式异常” | DB 实际 dimensions = {channelFit:32, trustPersuasion:20, ...} 6-key 对象,DimensionView.tsx 期望数组 → Array.isArray false fallback。改组件 normalize() 同时支持 array & object,object 用 DIM_LABELS 中文映射 |
| 全站图片大图 | 新 Lightbox.tsx Provider + useLightbox() hook,ZoomableImage.tsx 包装;root layout 挂 provider;report 页 2 处图片可点(素材 grid + 概念图缩略图);头像/二维码不动 |
.gitignore | 加 *.bak 防 CC 残留回归 |
R12(04-28,commit 3130f9d)— 首页读 session
爸爸误判”又要登录” —— 实际 cookie 完全有效,是 app/(marketing)/page.tsx 和 SiteNav 纯静态不读 session。修:marketing layout server 端 getSessionUser(),登录态右上角换”进入工作台”+ user chip,所有 7 处 <Link href="/login"> CTA 按 ctaHref = user ? "/app/chat" : "/login";/login 已登录直接 302 → /app/chat。footer 同步。verify 16/16。
R13(04-28,commit 88afea6)— 删死链
components/app/user-shell.tsx:20 写死 /app/projects/wuyi-tea/report(早期 demo 残留 → 404)。删之,/app/projects 高亮 match 简化为 p === "/app/projects" || p.startsWith("/app/projects/") 让 /report 子路径仍归”我的项目”。verify 7/7。
R16/R17/R18(04-29 晚)— Chat 引导卡 + onboarding 表单 + Prisma 真列
| 轮 | commit / deploy | 内容 |
|---|---|---|
| R16 | a57aefe / deploy 87396dae0b126ad1,verify 5/5 | chat 右侧 aside 加两张引导卡:「方案生成流程」(4 步紫色徽章)+「当前建议」(按 project.status 7 档动态) |
| R17 | bc48969 / 8aba24d13476412c,verify 7/7 | 首次进 chat 自动渲染 onboarding 表单卡(产品 / 品牌 / Logo / 包装类型 chip / 设计元素 chip / 风格 chip)→ 提交后创建 Project + 拼 prompt 当首条消息 → 切 active |
| R18 | 4ace72ec4de1696e,verify 10/10 | Prisma migration 20260429153158_* 加 4 个真列 packagingType / designElements / style / logoUrl;backfill 16 条;新增 /api/uploads/orphan onboarding 阶段 pre-create 上传 logo;回滚 R17 的字段映射”借壳” |
R17 借壳 → R18 backfill 事故(坑 #2)
R17 为图省事把新字段映射到老 schema 列上:packagingType→category、designElements→channels[]、style→priceTier、logoUrl 不持久化。后果:/admin → users → projects 看到的”价格带”其实是用户选的”风格”。
R18 加真列后想 backfill + 清空老列。Hermes 在 prompt 里武断写”同时清空 category/channels/priceTier”,CC 按字面执行 --apply。但那 16 条里有真实老业务数据(“植物饮品” / ["天猫","抖音"] / “中端”),被强行搬进 packagingType / designElements / style,语义全错。
教训:backfill 必须先 dry-run 看 sample 再 —apply;不能假设”R17 之前 DB 是空的”,要 query 验证。
R18 顺手把本地 ADMIN_SLUG 同步到 32 位 prod slug(ad7c3ec948e19de4bd13dc696d63cf85),CC 不再撞墙。
R19(04-29 晚)— 4 路并行 CC review + 11 个 P0 修复
跑 4 路并行 Claude Code review(A admin / B uploads / C credits / D wx OAuth),合计揪出 11 个 P0 漏洞。R19 单批 hotfix 落(部署 task proc_13ffbf093b12)。
关键修法
| 项 | 真因 + 落地 |
|---|---|
| idempotencyKey 三种格式同概念退款 | concept 退款历史用过 refund_concept_failed:<id> / concept-watchdog-<id> / refund_concept_timeout:<id> 三种前缀 → 同一笔可能多退。统一到 refund:concept:<id> 一条线 |
requireAdmin 仅信任 cookie | 旧逻辑只看 ph_role=admin cookie,cookie 可被伪造。改成必须 DB 二次校验 User.role=admin |
/internal-panel/* 公网可路由 | R15 把 app/__admin/ 重命名 app/internal-panel/ 修 Next.js private folder 不收的 build bug,但忘了加 /_a/ rewrite 守门 → /internal-panel/users 直接 200。补 middleware 强制 rewrite |
X-Forwarded-Host 完全可信 | finalize 拼 absolute URL 用 req.headers["x-forwarded-host"],攻击者改 header 可让回调跳任意域。新 lib/public-base.ts 加 host 允许列表,校验后才用 |
next start -p 3000 硬编码端口 | package.json scripts 写死 -p 3000 覆盖 PM2 的 PORT env → 端口冲突静默失败(同时把 menshen-ui 也咬了)。改 next start 让 env 生效 |
| WeChat finalize 重放窗口大 | 新 WxFinalizeNonce 表(openid + ts),相同 nonce 5 min 内拒掉 |
| 退款失败无补偿队列 | 新 RefundOutbox 表 + cron refund-outbox-flush(*/5 * * * *)+ refundOrEnqueue helper:直退失败转 outbox,cron 兜底重试 |
| 积分扣加非原子 | consumeCredits / grantCredits 改 SQL 单语句 + 强制 idempotencyKey 必填,类型签名也改成 required |
R20(04-29)— 入口收敛到 /app/chat?new=1
之前点「新项目」会 POST /projects 预建一条带「新项目」/new_brand 占位的空壳(首页/卡片/导航 4 处入口都这样)。结果 admin 看到一堆没填表的空项目。R20 拆掉所有 pre-create POST,新建项目统一跳 /app/chat?new=1 —— 用户先看引导卡(WhyChatFirstCard)再走 R22 的两步表单。第一条 onboarding 消息从 role=system 改 role=user(避免 LLM 把它当系统指令)。
R21(04-29)— 项目类型枚举对齐业务
之前 type 字段是 existing / new(继承自 R17 借壳期)。改为 redesign / new_brand / compare 三档,与品牌方实际诉求对应:
redesign— 改现有包装,必填pack_front上传(前包装图)new_brand— 全新品牌,无需上传compare— 多方案 PK,无需上传
Project.type migration 同步迁移历史数据(existing → redesign、new → new_brand)。
R22(04-29)— 两步 onboarding + WhyChatFirstCard
R17 的单步大表单太重劝退。拆成:
- Step 1:项目类型 picker(3 张大卡 redesign / new_brand / compare)
- Step 2:基础信息表单,
redesign类型下额外渲染pack_front可选上传槽(不上传也允许,admin 后台会标 incomplete)
Chat 第一屏新组件 WhyChatFirstCard 解释「为什么先聊再填表」,把转化路径从「填表→出图」拉到「聊→澄清→填表→出图」。
R14 → R15(04-29)— Admin 路径 /_a/<32-hex>/...
R14 落地 /<slug>/login 模式,但发现 user-menu 还显示 admin 入口 = 等于撒手没。R15 升级到铁律级硬标准:
- 路径:
/_a/<32-hex>/login、/_a/<32-hex>/users等。/_a/前缀仿_next/让扫描器跳过;32 hex slug = 128-bit 熵 - 认证:保留
ph_session+role=admin,沉淀 skill 时升级方案为独立ph_admincookie + 独立密码 - UI 不暴露:user-menu 不再显示 admin 入口
- 坑:Next.js 不路由
__前缀目录(private folder 约定)—— R14 的 CC 把源码搬到app/__admin/但 build 不收 → 改app/internal-panel/ - 当前 admin URL:
https://packhorizon.mvp.restry.cn/_a/ad7c3ec948e19de4bd13dc696d63cf85
沉淀 skill secure-admin-path-pattern(路径格式 + 独立认证 + UI 不暴露 + 老项目迁移步骤),所有新项目 scaffold 默认带这套。
Admin 后台页面清单
/admin 概览 / /users / /projects / /orders / /payments / /credit-logs / /asset-access-logs / /suppliers / /designers / /settings / /models ⭐ R10 加(概念图模型切换)。全部走 /_a/<slug>/* rewrite。
REVIEW_M1_M5d P0 余项(04-27)
- diagnose 模块缺图片上传 UI(后端就绪,前端没接)
- new-project 表单缺
targetAudience必填字段 - diagnose / brief 阶段 AI 失败时不退积分(concept 阶段已退)
/api/orders/topupfake “no-payment” 充值在 prod 暴露 → 必须 admin gate 或下线
营销页采用 styles.css + .ph-marketing class 前缀避免污染 /app /admin。
不变量
- AI 生成不存”草稿态” —— 用户看到的图必然已落 R2 + 资产审计
- 所有签名 cookie 加
__Host-前缀强制 HTTPS + path=/ - 业务方域名独立 → CORS 必须显式配(见 wx-gateway cors 白名单)
- 退积分必须 idempotencyKey 防双退(cron 重跑 + 手动重投不冲突)
R24 hotfix 续(05-08)— startsWith minified 崩溃 + callJson 超时三连提
R24 部署后线上偶发”点击「开始生成」按钮整页白屏”,控制台 TypeError: e.startsWith is not a function。
- 真因:
app/app/chat/page.tsx:523onConfirm={runFullGenerate}把 React 合成事件对象当首参传进runFullGenerate(projectId),projectId.startsWith(...)直接炸。minified 之后看不出。修:onConfirm={() => runFullGenerate(currentProjectId)}显式包一层。 callJson超时:进度卡里 7 步演戏,但底层 4 个 API 之一(/api/projects/.../generate-concepts走 Azure gpt-image-2)单次出图常 80–150s。原callJson30s 写死 → 第 5/7 步前端 timeout,但后端继续跑、偶发拿到结果时 UI 已经报 failed。两次上调:30s → 180s → 1800s(30 min),同时服务端maxDuration=1800一并放开。这一对超时必须前后端同步,否则一边 abort 一边 still running 状态对不齐。
R25(05-08)— 「继续聊 / 继续优化」入口(chat 支持 ?project=)
R20 把”新建项目”统一收敛到 /app/chat?new=1 之后,老项目”继续优化”没有入口——用户点生成记录详情页”继续优化”会跳回新建流程从头来。
R25 加 ?project=<id> 参数:/app/chat?project=<id> 进 chat 直接挂载该项目的历史 + 接着聊;不带 project 也不带 new 时仍按 R22 的 onboarding 走。生成记录详情页「继续聊」按钮指向 /app/chat?project=${projectId},不再开新 thread。
副作用一并修:active project 选择器 startsWith("/app/projects") 高亮误判(R13 之后没维护),改回精确 path 匹配。
R24(2026-05-07)— 后台信息架构重构 + 显式生成 + 进度演戏 + 三 CC 并发审
R24 是 PackHorizon 后台一次成体系重做:合并「我的项目」入「生成记录」/ AI 对话改纯新建入口 / 生成报告改显式触发 + 7 步进度动画 / 详情页加聊天回放。流程上首次跑通「Claude Code 批量改 → 多 CC 并发 review → review-verify-fix 实证 → hotfix」全链路,共 17 commits / 30 文件 / +900-250 行。
信息架构(IA)变更
| 项 | 之前 | 之后 |
|---|---|---|
| 侧栏 | AI 对话 / 我的项目 / 生成记录 / 充值与套餐 / 订单与服务 / 用户信息(6 项) | AI 对话 / 生成记录 / 开通会员 / 用户信息(4 项) |
| 「我的项目」 | 独立列表页 | 删除,合并到「生成记录」 |
/app/projects | 列表页 | 404(外部未发过 URL,不做 301) |
| 「订单与服务」 | 侧栏入口 | 撤掉(user-menu 仍可达) |
| 「充值与套餐」 | 名 | 改 「开通会员」 |
| AI 对话页 | 主区右侧带项目切换/列表面板 | 纯新建入口:打开就能聊,没有项目子列表 |
| 生成记录详情 | 直接看报告 | 顶部加**「需求对话回放」**可折叠面板(默认折叠) |
批次拆分(A / B+C / D)
| 批次 | 主题 | 关键改动 |
|---|---|---|
| A | 侧栏 + IA 收敛 | 侧栏 4 项;删 /app/projects;chat 页右侧项目切换器 + useEffect 删干净(CC 漏删 UI 组件本身,Hermes 自补 commit f2db8fc) |
| B+C | 显式生成 + 进度演戏 + 详情回放 + chat 文案 | Project.chatHistory JSONB 列(migration 已加,实际未读写 → R24 后续判定为死列);ConfirmGenerateCard(AI 输出 [GENERATE_READY]\n{json} 信号触发);GenerateProgress 前端假装 7 步、后端实际 4 个 API(不做真 SSE);详情页对话回放折叠面板;chat 文案:placeholder 改「先在上方完成新建项目的引导,再开始对话」(用户拍板:必须先建项目才能聊 = 设计如此) |
| D | P2 体验打磨(7 项) | 进度动画细化 / 确认卡微动效 / 卡片 hover 抬升+缩放 / 空状态插画 / 侧栏 active 浅紫底+左紫竖条 / 生成中全局 toast banner(D6) / 错误兜底文案 + 重试。砍掉的 3 项:流式打字(要 SSE 改架构)、报告页展开动画(锦上添花)、移动端 chat 适配(非 MVP 重点) |
关键决策
- 「修改记录」方案 A:只显示次数,不存历史版本(避免 schema 复杂度)
- 「继续优化」:回 chat 接着聊 + 加分隔标记,不开新 thread
- 进度条:「演戏」方案 — 前端 7 步 / 后端 4 个 API 调用,不上 SSE
/app/projects/[id]/report老 URL 直接换不加 301(外部未发过)- CC 调用模板:
cat /tmp/x.md | claude --print --model claude-opus-4.7-1m-internal --permission-mode bypassPermissions(不用 stdin 重定向,会丢内容) - 首页:用户已在 5-07 当日另行做完,R24 prompt 明确告诉 CC「首页不许碰」
三 CC 并发 review → 综合 B-
R24 改完 17 commit / 30 文件 / +900-250,触发多 agent 并发 review 阈值。三个 CC 各审一维度(Hermes 自合 verdict,不让 CC 自圆其说):
| 维度 | 评分 | findings |
|---|---|---|
| A. Security & Auth | B+ | 1 MED + 4 LOW |
| B. Behavior Parity | B- | 1 HIGH + 5 MED + 8 LOW |
| C. Robustness | B- | 2 SEV + 2 HIGH + 3 MED + 4 LOW |
总评 B-:能上线,但有几颗雷必须先拆。
review-verify-fix 实证(8 → 6 真 / 2 部分真)
按 review-verify-fix skill 派独立 CC 拿 grep / git show / 真复现验每一条(不让 review CC 自验):
| 项 | 原 review 结论 | Verify 判定 |
|---|---|---|
| V1 | chatHistory 死列 | 真 but 降 LOW(仅 nullable JSONB 占位,不影响功能) |
| V2 | F5 中途刷新进度卡死 + 输入锁死 + 重复扣 100 积分 | 部分真 — 卡死/锁死真。重复扣 100 是夸大:3 个 API 都有 5min bucket 幂等,5 分钟内 F5+重试不会双扣 |
| V3 | Banner + GenerateProgress 在 chat 页双显 | 真(1 行 pathname 判断能修) |
| V4 | 新 status diagnosing/generating/ready 后端从不写 | 真 but 降 MED(前端有兜底分支不会崩,纯文档不一致) |
| V5 | INSUFFICIENT_CREDITS 被 D7 通用 toast 吞了,丢「需要 X / 余额 Y」+ 充值 CTA | 真 |
| V6 | 「再补充一下」按了没用立刻重弹 | 部分真:不是”立刻”——下次发消息后才重弹,且这是有意设计(用户补充→重新征求确认) |
| V7 | Banner 2s 全局轮询 + ?limit= 服务端忽略 | 真(多 tab/后台 tab 持续轰 /api/projects 全表) |
| V8 | callJson 无 AbortController 无超时 | 真(unmount 后慢请求永久挂起) |
结论:review 方向都对,但 V2 把”5min 外可能重扣”夸大成”必然重扣 100”,V6 把设计当 bug。Verify 拦下了 V6 误报和 V2 恐慌叙事。
6 hotfixes(F1–F6,3 commit 合并提交)
- F1 Resume Card:
abortRef+ 中途刷新 / 失败时显式恢复入口(V2 修复主体) - F2 Banner 路径过滤:
usePathname在 chat 页隐藏<GenerationBanner />(V3) - F3 402 结构化 toast:
INSUFFICIENT_CREDITS单独分支跳/app/credits,恢复 CTA(V5) - F4
?limit=解析 + clamp:服务端真支持 limit,banner 调用减负(V7 一半) - F5
document.visibilityState暂停轮询(V7 另一半) - F6
AbortController+ 30s 超时包callJson(V8)
V1 / V4 / V6 按 verify 结论不修(死列不影响、文档不一致非阻塞、设计如此)。
最终一刀:删 <GenerationBanner />
部署后用户验收第一句反馈:「报告生成中… 第 6 步 / 7 — 为什么每个界面上面都有个这个 有什么用」。Hermes 解释 D6 的意图(切走 chat 仍能看进度+点击跳回),用户回**「多余」**,1 行删 mount,立刻重部署。
启示
- 用户「多余」反馈是高信号:D6 的全局 banner 看似友好实则视觉噪音。默认不加全局横幅,case-by-case 加。
- review 必走 verify:3 CC 综合 B- 看着吓人,verify 一过砍掉 2 条误报+大幅降级 V1/V4,真实修复面只剩 6 条 hotfix。
- CC 摆烂反问要直接拍板:批次 B+C 第一轮 CC 反问 4 个问题不干活,按 cc-anti-procrastination skill 不答只命令 → 第二轮全干完。
.nextcache 与pnpm build冲突会让 dev 起不来,dev 跑着别 build;要 build 先停 dev。- vision 截图易误读(“积分”是 CTA 不是 nav;“P” 是 logo mark)—— 拼接对比图字体路径还容易炸,4 张分开发 比拼一张稳。
架构图(04-29)
/tmp/packhorizon-arch.png + HTML 源 /tmp/packhorizon-architecture.html:6 层(Frontend / Edge / Database / Cloud AI / Security / Cron Bus)+ 6 张 info card 关键约束。
旧版 msdevhub(2026-03-24,BNEF Bot 部署)
当前 fries-mac 重起的项目之外,msdevhub GitHub 组织下另有一个同名 msdevhub/PackHorizon-Al,由 BNEF Bot 于 2026-03-24 在 Azure 东亚 VM 上一气呵成部署。两条线代码库不同、域名不同、技术栈不同,无代码继承;msdevhub 那条 04-27 后未见活跃,待新版稳定后再决定是否归档。
基础设施
| 属性 | 值 |
|---|---|
| VM 名称 | PackHorizon |
| Azure 区域 | 东亚 (East Asia) |
| VM 规格 | Standard_B2als_v2 |
| 公网 IP | 20.255.98.226 |
| SSH | ssh -p 18822 azureuser@20.255.98.226 |
| 开放端口 | 80, 443, 18822 |
| 域名 | pack.restry.cn |
| 证书 | Let’s Encrypt(有效期至 2026-06-22) |
| Web 服务器 | Nginx + PM2 |
部署架构 + Webhook
GitHub Push (main)
↓
Webhook → https://pack.restry.cn/deploy
↓
VM: git pull → npm install → build → pm2 restart
- Payload URL:
https://pack.restry.cn/deploy - Content type:
application/json - Secret:
packhorizon-deploy-2026 - Events:Just the push event
- Deploy Key:
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFkGma9tspObVqDZb2/Qqphe7GQTZTLrcrY5Aup2ZF3A
修复 + 凭据
- CORS:Fastify CORS 插件 origin 回调原本只放 localhost 回环,生产域名
pack.restry.cn被拒;修为非回环也通过 - 管理员:
operator.private@packhorizon.local/xAPVlvCnwZiyMoB0WLEWrMZ6
时间线
- 2026-03-24 17:25 — clone 项目到本地工作区
- 2026-03-24 19:07 — 创建 Azure VM(东亚,Standard_B2als_v2)
- 2026-03-24 19:19 — 部署完成,HTTP 可访问
- 2026-03-24 19:22 — 配置 HTTPS(pack.restry.cn + Let’s Encrypt)
- 2026-03-24 19:27 — 修复 CORS
- 2026-03-24 19:55–20:08 — GitHub Webhook 自动部署上线
相关
- wx-gateway — 登录 + 集中 access_token
- deployer — 部署
- image-studio — AI / Azure 凭证复用源
- packsmith — 同期姊妹项目
- monitoring-and-cron — concept-watchdog cron
- caddy-reverse-proxy — 反代
- bnef — BNEF Bot(旧版 msdevhub 部署 agent)
- azure-vm-management — Azure VM 管理(旧版)
- fries-mac — 新版开发主机