← Back

四月手记

决定、踩坑、和一些还没想清楚的事

月上半月干的事太多,不按时间写了,按主题。每段尽量把"发生了什么、踩了什么坑、最后怎么决定的"讲清楚,以后翻回来能用。


卖房

McVay,95127。2022 年 $1.47M 买的,首付 $220K。现在 Zillow 估 $1.44M。四年了,浮亏。

HELOC $360K 挂在 8.77% 浮动利率上,每月烧 $3K。James 四岁,三房不够住,爷爷奶奶来没客房。所以认真考虑卖。

估价

联系了四个 agent:Jing Xue(2022 年的买方 agent),Enrique Medellin,Nancy Reynolds,Barbara Bui。Jing 第一个回,给了 $1.4M 的 CMA,佣金只收 1%(正常 2.5-3%)。Enrique 回了,下周三来看房。Nancy 和 Barbara 还没回。

我不信任单一数据源。Chrome 爬了 95127 近 40 天的 41 套成交,deep-dive 了 5 套同档次 comp。

关键发现:之前用 14705 E Hills($740/sqft)做锚是错的。 那套 vinyl linoleum 地板,fixer 级别。McVay 有 granite countertop、tankless water heater、updated bath、city view——对标的是 5271 Summit($1,441K 成交,$970/sqft),renovated tier。

Zillow 在 95127 准得离谱。 5 套 comp 里 4 套 Zestimate 和成交价误差 <0.5%。唯一的 outlier 是 706 Linda Vista,差了 7.7%。所以 McVay 的 $1,443K Zestimate 可信度高。Jing 的 $1.4M 反而偏保守。

财务分析(踩坑重灾区)

做了四个版本。第一版结论 7.7 年回本,第四版 6 个月。 同一组数据,四个假设错误翻转了结论。逐个记下来:

坑 1:Federal/California 税率混算。 California 不 conform TCJA,mortgage interest deduction 上限是 $1M acquisition debt(Federal $750K)。Property tax 在 California 全额可抵(Federal 被 SALT $10K cap 吃掉)。California standard deduction 只有 ~$11K(Federal $29K)。分开算后,留房的税盾从"看起来很大"变成 $9,646/年。

坑 2:Security deposit 当永久损耗。 $7,500 deposit 不是花掉的钱,是资金占用。正确处理:opportunity cost = $7,500 × 3.29% / 12 ≈ $21/月。

坑 3:Maintenance cost 双重扣减。 净到手 $155K 已经扣了佣金和 closing cost,但 comparison 里又单独列了一遍。

坑 4:Opportunity cost 口径不一致。 SPAXX yield 按 after-tax 算,deposit 按 pre-tax 算。要么全 pre-tax 要么全 after-tax。

最终结论:

  • 卖 + 租 $5,500/月 → 月成本 $5,232
  • 留 + HELOC refi 到 6.5% → 月成本 $6,284
  • 卖房每年省 ~$12,600,一次性搬家成本 $6,500,约 6 个月回本
  • 但房子年涨 4% = $57K 增值 >> $12.6K 现金流差
  • 决策本质:现金流优化(卖)vs 资产增值押注(留)

HELOC Refi(不管卖不卖都该做)

CU 产品 利率
Star One Fixed HELOAN 15-20yr 6.46-6.57%
Star One Fixed-option HELOC 6.08-6.19%
Provident 5yr Fixed HELOC 6.00% intro → 7.20%+ APR
Meriwest Fixed HELOAN 8.50%(没意义)

Star One 6.5% fixed,年省 $8,172。 远超原来 ≤7.25% 的目标。CLTV 80.4%,卡在好利率的边界上。这周提交申请。


AMZN 减持

4 月 15 日卖了 150 股,$248.80/股,套现 ~$37K → Fidelity SPAXX(3.29%)。

集中度从 41% 降到 33%。健康线 15%,还差一倍。

税务策略

剩 145 股,cost basis $203.64。最早一批(2025-05-15 vest)5 月 15 日转长期资本利得,税率从 ~48% 降到 ~29%。145 股的 gain $6,549,等一个月省 ~$1,244。

516 股 unvested RSU 全部设了 Fidelity vest day "Sell All"。2026 全年 vest $102K,Amazon 默认扣 22% 联邦税,真实边际 ~48%。报税时要补 $20-25K。 必须预留。

QQQ 陷阱

直觉是拿卖股套现的钱买 QQQ 定投。但 QQQ ≈ 50% Top 10 科技股,其中 AMZN 占 ~6%。对一个拿 Amazon 工资、持有 33% AMZN 的人,买 QQQ 是三重科技敞口叠加。正确选择:VTI 或 VOO。

老婆的一万五

吴瑶有 $15K 在低息账户。转 Wealthfront 年化 4%,一年多 $450。没转。她的安全感比 0.7% 的利差重要。 别把家人的存款当需要优化的变量。


求职工具链

一周造了八个工具,零份简历投出去。

工具清单

工具 干什么 技术要点
~/bin/linkedin-jobs LinkedIn 职位搜索 v2 纯 curl,用 guest API endpoint(/jobs-guest/jobs/api/*),无需 auth/Chrome,1-2s/query
~/bin/levels-fyi 薪资校准 匿名抓 __NEXT_DATA__ JSON,slug 约定 company-title,零依赖
~/bin/job-tracker 求职 Pipeline 追踪 SQLite ~/.job-tracker/tracker.db,7 天自动 follow-up 提醒,按 source 漏斗统计
company-research skill 面试前公司情报 Perplexity + levels-fyi + LinkedIn Jobs 三源交叉
outreach-drafter skill LinkedIn 私信/冷邮件 7 条 anti-AI 规则,输出 2 变体
interview-coach-skill 面试教练 fork 自 noamseg 1,034 星项目(710KB 参考材料),23 命令,5 维评分
build-tailored-resume JD→简历 7 阶段 pipeline 含 ATS check + humanization pass
upwork-proposal Upwork 提案 fork 自 resume 架构,含 rate-sanity 拦截

LinkedIn Guest API

关键发现:LinkedIn 有一套完整的 guest endpoint 给未登录用户用,在 /jobs-guest/jobs/api/ 下面。搜索、JD 详情都有。v1 用 opencli+Chrome 要 8-10 秒一次查询,v2 纯 curl 1-2 秒。不需要 cookie,不需要 headless browser,不触发反爬。

Search Before Build

interview-coach 是第一次实践"先搜高星开源方案再决定自建还是采纳"。noamseg 的项目 1,034 星、710KB 参考材料、23 个命令覆盖 mock/analyze/stories/prep。自建的话至少两周。采纳只花了一个下午做适配。

Hermai.ai

评估了 hermai.ai 的 schema registry(181 个网站的 endpoint 定义)。结论:当字典用有用,但不能替代逆向工程。 LinkedIn 的 schema 对 auth 的描述就是错的——声称需要登录,实际有 guest endpoint。


cband 崩了

4 月 13 日,cband(claudraband)0.6.1 更新后 stdout 只返回 tool call markers(> Read+ tool),不返回 assistant text。

迁移

6 个 job 脚本从 cband-run 迁移到 claude -p/opt/homebrew/bin/claude):

  • pa-morning-summary、brightwheel-daily、morning-briefing、pa-uscis-daily、1p3a-watch、interview-digest
  • job-runner 的 Phase 2 self-heal 也迁移了

--cwd 是 cband 专有 flag,claude -p 不支持。提示词改为 temp file + cat | claude -p 管道模式。

踩坑:--max-turns 1 的陷阱

Sonnet 处理大输入(~80KB stdin + 复杂 prompt)时,可能先做 tool call 再输出文本,需要 >1 turn。--max-turns 1 会直接报 Error: Reached max turns (1) 退出。Haiku 不受影响。

规则: 简单提取任务 --max-turns 1 够用。大文件合并/结构化输出用 --max-turns 2 起步。别盲目优化到 1。

踩坑:stdin pipe pattern

大文件(>10KB)如果让 claude -p 自己读,--max-turns 的预算会被 CLAUDE.md 读取和文件分段读取吃掉。用 cat "$FILE" | claude -p 把数据直接灌进 prompt,绕过 tool call 开销。

E2E 验证规则(血的教训)

迁移完我说"done"。第二天所有 cron job 全挂了。明明有 Bash 可以跑 job-runner --test,但就是没跑。

从此以后的规则: 任何脚本/工具/cron 改动后,必须跑 job-runner --test <job> 并贴测试结果。不贴 PASS 证据不许说 done。


Chrome 僵尸

检查进程时发现 33 个 chrome-devtools-mcp 僵尸。最老的跑了好几天。三个大的分别 4.7GB、4.5GB、566MB。

原因: 每个 Claude Code session spawn 一个 chrome-devtools-mcp 实例,session 结束后不退出。

修复:

  1. 集中到共享 chrome-mcp-shared PM2 服务,端口 9340
  2. zombie-mcp.js 健康检查:自动杀运行 >6h 或 RSS >500MB 的进程
  3. 接入每小时 system-agent

Effectiveness Benchmark

从 spec 到上线一个 session 搞定。

  • 路径: ~/clawd/effectiveness/,Dashboard 在 :4000/effectiveness
  • 四个维度: reliability、speed/resources、zombie detection、ROI
  • 数据: SQLite WAL,从 ~/jobs/logs/ 一次性导入 5,940 条历史指标。job-runner post-hook 自动写入新指标
  • Build cost 公式: (total_commits × 0.5h) + (first_week_commits × 0.5h)——粗糙但够用
  • AI 评估: claude -p --model sonnet --max-turns 1 批量打分
  • 7 天 burn-in: 新工具前 7 天不判 zombie/negative-ROI,因为新东西总是不稳定

发现

  • ralph-loop:从来没成功跑过。僵尸。
  • interview-digest:75% 失败率。已修。
  • 4 条替换链自动检测(工具 A 替换了工具 B)。

磁盘

/System/Volumes/Data 持续 85-89%。system-agent 每小时跑清理,每次卡在同一个地方。

三个无法自动解决的大头

大小 为什么删不了
Chrome code_sign_clone ~14GB+ Chrome 在运行,lsof 有句柄,CLAUDE.md 禁止杀 Chrome
/private/var/folders 孤立克隆 曾发现 47 个目录 61GB 需要 Chrome 不在运行时清理
Plex metadata ~56GB 在外置 ORICO 盘上,不影响系统盘(这个是误报)

现状: npm/pip cache 清理只回收几百 MB。docker prune 永远失败(Docker Desktop 没运行)。self-heal cron 陷入西西弗斯循环——每小时检查、发现、尝试、失败、下次再来。

正确解法: 安排 Chrome 离线时段做 code_sign_clone 清理。目前还没做。


零碎但值得记住的

Inkplate e-ink 仪表盘

已上墙。ESP32,1280×720,3-bit grayscale。Deep sleep 模式:90 秒 awake + 9 分钟 sleep。

硬件坑汇总(全是实测踩出来的):

  • sph_pin 是 GPIO 33 直连,不在 pca6416a 扩展器上。配错了只会显示两条竖线。
  • 显示翻转用 sharp.flip(),不是 .flop()。搞反了挂墙上是倒的。
  • sharp.composite().flip() 之后执行,overlay 不会跟着翻。解法:把图片嵌进 SVG 的 <image> 标签,跟整个 SVG 一起翻。
  • SVG <image> 嵌入的图片必须预先 resize 到目标尺寸——sharp/librsvg 忽略 SVG 的 width/height 属性,按原始像素渲染。一张微博图 560px 高直接盖住了底部一整行。

OTA 流程(设备大部分时间在 deep sleep,抓不到):

  1. curl 'http://localhost:4000/inkplate/ota?set=1' — 设 OTA flag
  2. 等最多 ~10 分钟设备醒来
  3. esphome upload inkplate-dash.yaml --device inkplate-dash.local
  4. curl 'http://localhost:4000/inkplate/ota?set=0'

Video Server Shuffle 算法

"全部随机"按钮之前只 shuffle 当前目录。重写为分层加权:

  • 按父目录分组,组内 Fisher-Yates 随机
  • 组间权重 = remainingCount ^ 0.5(指数 0 = 小目录过度采样,1 = 纯均匀,0.5 = 折中)
  • 反连续约束:追踪 lastPoolIdx,下一次不能从同一目录选
  • 根目录占了 54% 的视频,播放列表尾部不可避免地聚集——这是结构性的,不是 bug

Zillow 租房 Pipeline

4x/天(9/13/17/21)扫 SJ+Milpitas 4+bed SFH/TH ≤$6K。AutoScore 0-100 分,≥70 推飞书。

Zillow 搜索 URL 的 7 个坑:

  1. 过滤器是排除制——要排除 apartment/condo/multi-family,不能只选 SFH
  2. regionSelection 必须带 regionId+regionType,光靠 URL 路径不够
  3. 默认排序 priorityscore 会把公寓广告推到前面,要用 sort:{value:'days'}
  4. 分页路径是 /rentals/2_p/,不是 ?page=2
  5. Chrome 147+ 的 CDP /json/new 必须用 PUT,GET 返回 Using unsafe HTTP verb
  6. __NEXT_DATA__ 里的公寓 zpid 是 lat/lng 字符串不是数字,要 /^\d+$/.test(zpid) 过滤
  7. stories 字段在搜索结果里几乎永远是 null(82/83 条),要从描述文本推断

评分踩坑:unknown 字段给了满分。 82 条数据 stories 是 null,代码默认给 10/10。一个三层 townhouse 靠缺失数据拿了 77 分推到了飞书。规则:null 给中位分(5/10),永远不给满分。

Kiro CLI 毁了 .zshrc

安装 Kiro CLI 后,它往 .zprofile.zshrc 注入了自己的代码块。结果 .zshrc 看起来被清空了,tmux-maintplay alias 丢失。手动清理,Kiro 已从系统删除。

ESM import() 执行 main()

pre-send-hook.js 底部有 main() 调用,没有 guard。其他三个服务(feishu-proxy、wecom-bot、tel-bot)await import() 它的时候,main() 在它们的进程上下文里执行了。process.argv 没有预期参数 → process.exit(1) → 导入方直接挂了。

ESM 没有 CJS 的 require.main === module。解法:用 import.meta.url 对比 process.argv[1] 做 guard。

JSON config 文件被 Write 覆盖

用 Write 工具往 .mcp.json 加一个 leetcode 条目,结果把整个文件重写了,chrome-browser 条目被吞。花了一整个 session 排查"谁删了我的 MCP 配置"。

规则: 多条目 config 文件必须 Read → Edit(局部替换),不能 Write 整文件。

Stale-While-Revalidate Pattern

Inkplate 的 getWeiboHot() 要 spawn 子进程跑 30-60 秒。直接在 Express handler 里调会挂请求。

解法是模块级缓存 + 后台刷新:

let cache = { data: null, ts: 0, fetching: false };
async function getThing() {
  if (cache.data && Date.now() - cache.ts < TTL) return cache.data;
  if (!cache.fetching) {
    cache.fetching = true;
    fetchInner().then(d => {
      if (d) { cache.data = d; cache.ts = Date.now(); }
      cache.fetching = false;
    });
  }
  return cache.data; // stale or null on first call
}

第一次请求返回 null(skeleton 渲染),后台填充,后续请求秒回。fetching flag 防重复 spawn。

Auto-Reflect

问题:老是忘记跑 /session-reflect,每次还要 2-3 分钟。

方案:com.vigoose.auto-reflect LaunchAgent,每 30 分钟检查有没有已结束的 session。有的话:JSONL 压缩到 25K chars → claude -p sonnet 提取记忆 → 写文件 + session card + git commit。99% 的时候检查完没事做,成本约零。触发时 20-30 秒跑完。

手动的 /session-reflect 还在——热上下文提取质量更高。auto-reflect 是兜底网。


还没决定的事

  • 房子: 等 Enrique 下周三的 CMA,再等 Nancy/Barbara。三个估价齐了再做决定。HELOC refi 不等,本周申请。
  • 工作: Databricks 是 Tier 1 目标。但还没点 Apply。
  • 磁盘: 需要安排 Chrome 离线清理,但一直没排进去。

没有结论。有些事情就是还没想清楚。