Skip to content

chore(stack): 栈式合流收尾——把 #117/#118/#120(经 #128/#129/#130)的内容带入主线 - #134

Merged
Danceiny merged 20 commits into
feat/session-hotel-train-doctorfrom
stack/d30-115
Sep 4, 2026
Merged

chore(stack): 栈式合流收尾——把 #117/#118/#120(经 #128/#129/#130)的内容带入主线#134
Danceiny merged 20 commits into
feat/session-hotel-train-doctorfrom
stack/d30-115

Conversation

@Danceiny

@Danceiny Danceiny commented Sep 4, 2026

Copy link
Copy Markdown
Owner

用途(分支清理前置步)

分支清理盘点发现:feat 线已含 #112-#116/#119 的全部内容,但 #117(商店版自适应)/#118(酒店事实闸)/#120(legacy vendored 移除)的内容只在 stack/d30-115 上(经 #128/#129/#130 合入本栈),feat 线缺少 needsExtensionSummary/factsFromHotel 等交付物(内容键抽查 0 处)。

本 PR = stack/d30-115 → feat 线的合流:零新内容,只把三个已关闭 issue(评注见 #117/#118/#120)的已落地变更带入主线。合并后即可删除 stack/d30-115 分支,完成远程分支清理。

内容 = 已关闭 issue 的已验证变更

验证

各 PR 建立时均已过 run-all ALL SUITES GREEN;diff = feat 线与 stack/d30-115 的树差(仅上述三项)。

* feat(session): 会话面接通携程酒店(kind=hotel)——2026-09-02 迪拜 session「要订酒店却无机酒通道」的收官

为什么:账号会话通道(用户登录态,最强通道)此前只实现机票;用户要「携程找
酒店」时,agent 只能去撞 flyai 429 与打码 web 读页。本提交把酒店贯通会话面
五层:扩展注入(hotels.ctrip.com content scripts)→ 嗅探(URL hint 多版接口名
+ 形状签名兜底,对接口改名免疫)→ background per-site 白名单/SITES 注册 →
sessionHotelSearch(节律/登录/挑战红线/证据链与机票同构)→ gotry_session_search
kind=flight|hotel 路由。

- 扩展 0.2.0:manifest 双站点注入;content-main 酒店 URL hints + 形状嗅探
  (hotelList/hotelMatchInfos/hotelName 签名,2MB 上限,机票面行为零变化);
  background SITES += ctrip-hotel + per-site 检索白名单
- 适配器 adapters/ctrip-hotel.ts:entry URL(cityId 显式覆盖 + D-13 起步码表,
  词表外不猜 id——城市未收录时指引 web 搜 list 页取 city= 数字,不造数);
  走形解析器归一化 名/价/星/评分/地址/hotelId→jumpUrl(预订由人在落地页完成);
  打码价原样保留不数值化。接口面为公开常识口径,首个真会话后校准(D-13)
- effect 解译器:SESSION_HOTEL_SEARCH(浏览器通道,永不重试/不熔断,风控红线
  与 SESSION_FLIGHT_SEARCH 同款);ReadGuard 对酒店下单/支付 URL 照常物理拦截
- 测试:session-tests K 段(entry/走形/签名/闸面,68 pass)+ extension-tests
  §38 防漂移扩展(双站点注入/hotel hints 对账/形状签名逐字一致/per-site 白名单
  + 车道闭环 hit,27 段)+ smoke 会话酒店路由短路检查;全栈回归 ALL SUITES GREEN

保鲜清单勾稽(§11,非 M-exit):①§1.2 检索类已同步(ctrip-hotel 会话面);
②§9 让渡(能力增量,叙事归 CHANGELOG);③§10 让渡(无新增债务);④roadmap
让渡(不动里程碑定位);⑤README 中英当前形态已同步(工具行+状态段);
⑥stage1 状态头让渡(非 Stage-1 范围)。已知限制(诚实面):城市码表起步仅
沪/京,其余城市须 cityId;酒店接口面与城市 id 均待首个真会话实测校准。

* fix(tools): 迪拜 session 轨迹复盘——可选依赖不撒手,doctor 体检面接管状态与补装引导

为什么:286786a 把 hbcli/agent-reach 装配移出 setup 后,工具层仍按「包内 .venv
已装配」运行——npm 形态用户(2026-09-02 迪拜订酒店 session)的 gotry_agent_reach /
gotry_web_search 全量 not-installed,报错还指向已失效的文档;flyai 匿名试用额度
达限(共享池 429)被当通用 error,LLM 跨轮盲重试 4 次;hbcli hotel-list 冷启动
30s 超时无重试。founder 拍板:「不管」只指 dsh 自身 API key;可选依赖要主动
显示状态、引导重装。

- doctor 体检面(新):capabilities/doctor.ts 逐项只读分级(ok/degraded/missing:
  扩展/agent-reach .venv/hbcli 凭证/FlyAI key/sidebar),LLM key 显式让渡给 dsh
  宿主;CLI `npx gotry doctor [--fix]`(bootstrap 复用三个安装器)+ MCP
  `gotry_doctor` 工具,报告落 gotry-state/doctor-report.md(dsh 侧栏工作台可预览);
  not-installed/needs-setup 报错文案统一改指 doctor
- flyai:429 Trial limit reached → verdict='needs-setup' + setup 指引(申请入口 +
  FLYAI_API_KEY + 勿重试明示),机/火/酒三条 summary 分支与工具描述同步;
  factsFromFlyai 对 needs-setup 不落事实(同 error:无结论不是证据)
- effect 解译器:HBCLI 三效应重试策略「永不」→「仅 timeout 类 2 次」——上游
  冷启动建后端 session 可超时(spec 级 isRetryable;ENOENT/退码类「切换不是重试」
  契约不变);docs/effect-interpreter.md §3 策略表逐行更新
- smoke:flyai live 断言区分配置态(needs-setup→验 setup 指引合同)与代码故障
- 测试:doctor-tests 新建(6 段,注入式三态/让渡面/报告渲染/工具面落盘)+
  flyai 5/5 + effect 11/11 + bootstrap 8/8,全注册进 run-all-tests.sh;
  全栈回归 ALL SUITES GREEN

保鲜清单勾稽(§11,非 M-exit):①§1.2 已加自检类行;②§9 让渡(能力增量,无里程碑
事件,叙事归 CHANGELOG);③§10 让渡(无新增债务——本次修复的正是让出错位的形态);
④roadmap 让渡(不动里程碑定位);⑤README 中英当前形态已同步(doctor 入口/工具行/
flyai 勘误);⑥stage1 状态头让渡(非 Stage-1 范围)。

* feat(session): 会话面接通 12306 火车(kind=train)——机/酒/火三通道收官

为什么:继酒店(2435e09)后,会话面把最后一块拼图补上。12306 余票查询是
公开面(登录只关系下单),所以火车通道刻意无登录闸——诚实标注「公开查询面」,
不为通道一致性而虚构登录检查;列表接口不含票价,如实只呈现车次/时刻/历时/
余票,票价指回 12306 落地页(不伪装价格)。

- 适配器 adapters/rail-12306.ts:entry URL(fs/ts=城市名,电报码;D-13 起步码表
  32 城,词表外不猜码——未收录时指引 web 搜 kyfw 查询页 URL 取三位码显式传入);
  leftTicket/query 管道行解析(经典 | 拼接格式),行级签名校验(车次码+时刻形态)
  兜住索引漂移——失配整行跳过,fail-visible 不造数;余票分桶为公开常识索引口径,
  D-13 首个真会话后校准
- 扩展 0.3.0:content scripts 注入 kyfw/www.12306.cn;火车 URL hint
  (leftTicket/query 负载均衡变体全命中);background SITES += train-12306
  (无票据名,诚实空表)+ per-site 白名单 kyfw
- effect:SESSION_TRAIN_SEARCH(浏览器通道,永不重试/不熔断);工具面
  kind=train 过去日期代码层拦截 + summary 指明「列表接口无票价」
- 测试:session-tests L 段(entry/管道行/签名防漂移/闸面,82 pass)+
  extension-tests §38 防漂移(四站点注入/火车 hints 对账/SITES)+ 车道闭环
  train hit + smoke 火车路由短路检查;全栈回归 ALL SUITES GREEN

保鲜清单勾稽(§11,非 M-exit):①§1.2 检索类已同步(会话检索 机/酒/火);
②§9 让渡(能力增量,叙事归 CHANGELOG);③§10 让渡(无新增债务);④roadmap
让渡;⑤README 中英已同步(工具行+状态段);⑥stage1 让渡。已知限制(诚实面):
电报码表 32 城公开常识口径、余票座位桶索引为公开常识口径——均待首个真会话
实测校准;与 flyai search-train 平铺互补(flyai 试用额度达限期间会话火车是
主力火车实时源)。

* fix(session): 12306 适配器第一方校准——电报码 129 城 + 座位桶索引对齐官方 cN

为什么:上一版电报码表(32 城)与座位桶索引是「公开常识口径,首个真会话后
校准」——真去核对官方源头时发现两边都与现行官方映射不符(南宁 NIZ 实为
NNZ;座位桶 19-28 段旧索引与官方前端 cN(result,map) 转换函数不符,站名
/座位桶会全错)。与其等真会话暴露,不如直接对齐第一方来源:

- 电报码表逐条核对自 kyfw 官方 station_name.js 全量站表(129 城,
  快照 data/stations-12306-verify.json + session-tests L 段防漂移断言锁死)
- 座位桶索引/站名映射取自官方前端 queryLeftTicket_end_js.js 的 cN()
  (站名=data.map[电报码];座位桶 20-33 官方字段逐一对齐,行级签名校验
  继续兜住未来漂移);arriveDayDiff 删除(官方 DTO 无此字段,不造数)
- 测试:探针行按官方索引程序化构造逐桶锁定;extension-tests fixture 同步

保鲜清单勾稽(§11,非 M-exit):①§1 让渡(形态不变);②§9 让渡(叙事归
CHANGELOG);③§10 D-13 已同步(第一方校准部分清偿);④roadmap 让渡;
⑤README 让渡(工具面不变);⑥stage1 让渡。全栈回归 ALL SUITES GREEN。

* fix(session): 酒/火两通道真数据校准 + 扩展版本跟随主版本(0.0.1-rc.N)

为什么:上两个提交的酒/火通道带着「公开常识口径,首个真会话后校准」的已知
限制——founder 指示 todo 要自己跟进。本轮不用真会话就完成了大部分校准:
全部用官方/一方数据源,真错在首查前被抓掉。

- 12306 电报码表:自官方全量站表(station_name.js,3384 站)逐条校准——
  **纠出南宁 NIZ→NNZ 真错码**;扩到 129 城(含丽江/大理/香格里拉/拉萨等全部
  热门目的地);核对快照落 data/stations-12306-verify.json,测试逐条锁定
- 12306 座位桶索引:**第一方校准**——自官方前端 queryLeftTicket_end_js.js 的
  cN(result,map) 转换函数逐字段提取。旧公开常识索引(19-28 段)与官方现行
  映射全错(站名不在 15/16,而是 data.map[电报码];座位桶实为 20-33 段,
  gg/gr/qt/rw/rz/tz/wz/yb/yw/yz/ze/zy/swz/srrb)——原解析遇真回包会整行
  签名失配,首查必 miss,本轮提前修复;测试用下标探针行锁官方映射
- 携程酒店城市 id:探测法 + list 页 <title> 逐条验证(曾纠出 104=平遥县、
  14=苏州 等 5 处错猜——猜测直接进表会是数据灾难),实测 35 城入表,含
  **迪拜=220**(轨迹里 agent 构造的 id 正确)、丽江=37、大理=36、三亚=43
- 携程接口/形状:接口路径一方确认 restapi/soa2/34951/fetchHotelList(URL hint
  + content-main 嗅探面同步);解析器加「hotelInfo 包裹」结构化通道(SSR 实测
  形态:nameInfo.name/hotelStar.star/commentInfo.commentScore + 价格子树探测),
  通用走形兜底不变
- 版本跟随主版本(founder 拍板):manifest version_name = package.json 原样,
  version = 四段投影(0.0.1-rc.N → 0.0.1.N,Chrome manifest 只收点分整数);
  dist-manifest 校验放开 1-4 段;§38 加版本跟随防漂移断言
- 扩展 0.0.1-rc.18 已落位 ~/.gotry/extension(四站点注入),用户 Chrome
  chrome://extensions 里点一次重载即生效
- 测试:session 107/107(电报码防漂移/官方索引探针/真实形状 fixture)+
  §38 28 段(版本跟随)+ distribution 36/36;全栈回归 ALL SUITES GREEN

* fix(session): 携程酒店价格路径第一方校准——roomInfo[].priceInfo.price

为什么:上一提交把酒店价格字段留作「等首个真会话终验」——不需要等:接口直连
复现虽被 hotel-spider-defence 反爬 404(「让站点自己发请求」正是会话桥的设计
原因),但官方前端是公开静态资产,顺 webpack 运行时 chunk 映射逐个反查,list
页 bundle 的响应映射段把价格路径完整写明了。

- 官方路径:条目 = hotelList[].hotelInfo{summary{hotelId,nameInfo{name,
  names[]},hotelStar{star},positionInfo},commentInfo{commentScore},roomInfo[]};
  明文价 = roomInfo[].priceInfo.price(多房型取最低;页面 room_price 即读此);
  displayPrice 字符串价原样保留(打码口径);酒店名主路径 nameInfo.names[0]
- 加密价红线:priceToken 在而无明文 price = fetchHotelListPrices 解密链路的
  加密态,解密发生在页面内存,嗅探面天然拿不到——条目保留(名/星/评分照常),
  价如实为 0,不伪造任何数字
- 解析器:结构化候选按官方路径重写(roomInfo 优先 → price/amount 族子树探测
  殿后);通用走形兜底不变
- 测试:session 110 pass(多房型最低价/加密价不伪造/displayPrice 打码 三组
  新 fixture)+ §38 28 段 + smoke OK;全栈回归受影响面全绿

---------

Co-authored-by: Danceiny <danceiny@gmail.com>
* refactor(turn-deadline): 产品路径不装闸,benchmark 路径换成 wall-clock(ADR-24)

轨迹(dh 用户安排行程)显示原「步数预算」是评测闸,误装到产品路径
导致模型在 EXHAUSTED 后继续派发工具、token 截断、用户拿不到行程。
ts/src/tool-budget.ts → ts/src/turn-deadline.ts,语义换为 wall-clock
(默认 60s 软阈 / 120s 硬阈,env 可覆盖);产品路径 install() 默认
不调用,benchmark opt-in 才装;同步收紧工具 schema(同一 step 内
不会再回环);run-all §45 改名 + 加 enabled:false 产品路径不变量断言。

* feat(turn-policy): turn 预算 = 路由 + wall-clock 双出口(ADR-24 v2)

固定阈值(60s/120s)仍是「到点杀 turn」形态,轨迹失败模式照旧。v2 把
复杂度映射到出口结构:确定性路由器(turn-policy.ts,零 LLM,Tier 0 信号:
日期跨度/约束词/长度)把每轮分为 quick/sync/deep;deep-planning 硬阈出
口是 handoff——落 gotry_turn_handoff.v1 工单(独立格式,async-collect 对
无 spec state 会假失败,收集器留给 loopx tick)+告知用户 ETA,而不是逼出
没有证据的 final。产品路径默认装(路由+handoff 是产品行为);benchmark
钉固定 policy 保可复现;E2E/测试经 GOTRY_TURN_HANDOFF_ROOT 钉隔离根,
不触创始人真实 gotry-state。§45 = 路由表测(轨迹原文为回归锚点)+ Cordis
集成 + 打包二进制 handoff E2E,全绿。

* feat(turn-handoff): 收集闭环——「一小时后回来看看」的后台半段(ADR-24 v2 补全)

handoff 只兑现了承诺的落单,没人收单。本笔补收集器/复访/递归防护三件:
scripts/turn-handoff-collect.ts(单张/--all;GOTRY_HANDOFF_CHILD=1 派生子
规划会话,唯一出口 converge+长 leash 防无限递归,父进程数值 pin/工单根
在子环境清除;settleTurnHandoffTicket 原子结算交付物;终态幂等复诵零重
算,failed 交付物是诚实失败说明);只读复访工具 gotry_turn_handoff_list
(用户回问「规划好了吗」时模型查状态+交付物摘录,禁止编造);终态合同
gotry_turn_handoff_terminal.v1(succeeded exit 0/failed exit 2)。§45 E2E
以真打包二进制跑通 handoff→收集→settled→交付物全链,ALL SUITES GREEN。

* fix(test): 收集器「最新优先」断言去 flaky——同毫秒双单钉定 requestedAt 顺序

* feat(session): 会话面接通携程酒店(kind=hotel)——2026-09-02 迪拜 session「要订酒店却无机酒通道」的收官

为什么:账号会话通道(用户登录态,最强通道)此前只实现机票;用户要「携程找
酒店」时,agent 只能去撞 flyai 429 与打码 web 读页。本提交把酒店贯通会话面
五层:扩展注入(hotels.ctrip.com content scripts)→ 嗅探(URL hint 多版接口名
+ 形状签名兜底,对接口改名免疫)→ background per-site 白名单/SITES 注册 →
sessionHotelSearch(节律/登录/挑战红线/证据链与机票同构)→ gotry_session_search
kind=flight|hotel 路由。

- 扩展 0.2.0:manifest 双站点注入;content-main 酒店 URL hints + 形状嗅探
  (hotelList/hotelMatchInfos/hotelName 签名,2MB 上限,机票面行为零变化);
  background SITES += ctrip-hotel + per-site 检索白名单
- 适配器 adapters/ctrip-hotel.ts:entry URL(cityId 显式覆盖 + D-13 起步码表,
  词表外不猜 id——城市未收录时指引 web 搜 list 页取 city= 数字,不造数);
  走形解析器归一化 名/价/星/评分/地址/hotelId→jumpUrl(预订由人在落地页完成);
  打码价原样保留不数值化。接口面为公开常识口径,首个真会话后校准(D-13)
- effect 解译器:SESSION_HOTEL_SEARCH(浏览器通道,永不重试/不熔断,风控红线
  与 SESSION_FLIGHT_SEARCH 同款);ReadGuard 对酒店下单/支付 URL 照常物理拦截
- 测试:session-tests K 段(entry/走形/签名/闸面,68 pass)+ extension-tests
  §38 防漂移扩展(双站点注入/hotel hints 对账/形状签名逐字一致/per-site 白名单
  + 车道闭环 hit,27 段)+ smoke 会话酒店路由短路检查;全栈回归 ALL SUITES GREEN

保鲜清单勾稽(§11,非 M-exit):①§1.2 检索类已同步(ctrip-hotel 会话面);
②§9 让渡(能力增量,叙事归 CHANGELOG);③§10 让渡(无新增债务);④roadmap
让渡(不动里程碑定位);⑤README 中英当前形态已同步(工具行+状态段);
⑥stage1 状态头让渡(非 Stage-1 范围)。已知限制(诚实面):城市码表起步仅
沪/京,其余城市须 cityId;酒店接口面与城市 id 均待首个真会话实测校准。

* fix(tools): 迪拜 session 轨迹复盘——可选依赖不撒手,doctor 体检面接管状态与补装引导

为什么:286786a 把 hbcli/agent-reach 装配移出 setup 后,工具层仍按「包内 .venv
已装配」运行——npm 形态用户(2026-09-02 迪拜订酒店 session)的 gotry_agent_reach /
gotry_web_search 全量 not-installed,报错还指向已失效的文档;flyai 匿名试用额度
达限(共享池 429)被当通用 error,LLM 跨轮盲重试 4 次;hbcli hotel-list 冷启动
30s 超时无重试。founder 拍板:「不管」只指 dsh 自身 API key;可选依赖要主动
显示状态、引导重装。

- doctor 体检面(新):capabilities/doctor.ts 逐项只读分级(ok/degraded/missing:
  扩展/agent-reach .venv/hbcli 凭证/FlyAI key/sidebar),LLM key 显式让渡给 dsh
  宿主;CLI `npx gotry doctor [--fix]`(bootstrap 复用三个安装器)+ MCP
  `gotry_doctor` 工具,报告落 gotry-state/doctor-report.md(dsh 侧栏工作台可预览);
  not-installed/needs-setup 报错文案统一改指 doctor
- flyai:429 Trial limit reached → verdict='needs-setup' + setup 指引(申请入口 +
  FLYAI_API_KEY + 勿重试明示),机/火/酒三条 summary 分支与工具描述同步;
  factsFromFlyai 对 needs-setup 不落事实(同 error:无结论不是证据)
- effect 解译器:HBCLI 三效应重试策略「永不」→「仅 timeout 类 2 次」——上游
  冷启动建后端 session 可超时(spec 级 isRetryable;ENOENT/退码类「切换不是重试」
  契约不变);docs/effect-interpreter.md §3 策略表逐行更新
- smoke:flyai live 断言区分配置态(needs-setup→验 setup 指引合同)与代码故障
- 测试:doctor-tests 新建(6 段,注入式三态/让渡面/报告渲染/工具面落盘)+
  flyai 5/5 + effect 11/11 + bootstrap 8/8,全注册进 run-all-tests.sh;
  全栈回归 ALL SUITES GREEN

保鲜清单勾稽(§11,非 M-exit):①§1.2 已加自检类行;②§9 让渡(能力增量,无里程碑
事件,叙事归 CHANGELOG);③§10 让渡(无新增债务——本次修复的正是让出错位的形态);
④roadmap 让渡(不动里程碑定位);⑤README 中英当前形态已同步(doctor 入口/工具行/
flyai 勘误);⑥stage1 状态头让渡(非 Stage-1 范围)。

* feat(session): 会话面接通 12306 火车(kind=train)——机/酒/火三通道收官

为什么:继酒店(2435e09)后,会话面把最后一块拼图补上。12306 余票查询是
公开面(登录只关系下单),所以火车通道刻意无登录闸——诚实标注「公开查询面」,
不为通道一致性而虚构登录检查;列表接口不含票价,如实只呈现车次/时刻/历时/
余票,票价指回 12306 落地页(不伪装价格)。

- 适配器 adapters/rail-12306.ts:entry URL(fs/ts=城市名,电报码;D-13 起步码表
  32 城,词表外不猜码——未收录时指引 web 搜 kyfw 查询页 URL 取三位码显式传入);
  leftTicket/query 管道行解析(经典 | 拼接格式),行级签名校验(车次码+时刻形态)
  兜住索引漂移——失配整行跳过,fail-visible 不造数;余票分桶为公开常识索引口径,
  D-13 首个真会话后校准
- 扩展 0.3.0:content scripts 注入 kyfw/www.12306.cn;火车 URL hint
  (leftTicket/query 负载均衡变体全命中);background SITES += train-12306
  (无票据名,诚实空表)+ per-site 白名单 kyfw
- effect:SESSION_TRAIN_SEARCH(浏览器通道,永不重试/不熔断);工具面
  kind=train 过去日期代码层拦截 + summary 指明「列表接口无票价」
- 测试:session-tests L 段(entry/管道行/签名防漂移/闸面,82 pass)+
  extension-tests §38 防漂移(四站点注入/火车 hints 对账/SITES)+ 车道闭环
  train hit + smoke 火车路由短路检查;全栈回归 ALL SUITES GREEN

保鲜清单勾稽(§11,非 M-exit):①§1.2 检索类已同步(会话检索 机/酒/火);
②§9 让渡(能力增量,叙事归 CHANGELOG);③§10 让渡(无新增债务);④roadmap
让渡;⑤README 中英已同步(工具行+状态段);⑥stage1 让渡。已知限制(诚实面):
电报码表 32 城公开常识口径、余票座位桶索引为公开常识口径——均待首个真会话
实测校准;与 flyai search-train 平铺互补(flyai 试用额度达限期间会话火车是
主力火车实时源)。

* fix(session): 12306 适配器第一方校准——电报码 129 城 + 座位桶索引对齐官方 cN

为什么:上一版电报码表(32 城)与座位桶索引是「公开常识口径,首个真会话后
校准」——真去核对官方源头时发现两边都与现行官方映射不符(南宁 NIZ 实为
NNZ;座位桶 19-28 段旧索引与官方前端 cN(result,map) 转换函数不符,站名
/座位桶会全错)。与其等真会话暴露,不如直接对齐第一方来源:

- 电报码表逐条核对自 kyfw 官方 station_name.js 全量站表(129 城,
  快照 data/stations-12306-verify.json + session-tests L 段防漂移断言锁死)
- 座位桶索引/站名映射取自官方前端 queryLeftTicket_end_js.js 的 cN()
  (站名=data.map[电报码];座位桶 20-33 官方字段逐一对齐,行级签名校验
  继续兜住未来漂移);arriveDayDiff 删除(官方 DTO 无此字段,不造数)
- 测试:探针行按官方索引程序化构造逐桶锁定;extension-tests fixture 同步

保鲜清单勾稽(§11,非 M-exit):①§1 让渡(形态不变);②§9 让渡(叙事归
CHANGELOG);③§10 D-13 已同步(第一方校准部分清偿);④roadmap 让渡;
⑤README 让渡(工具面不变);⑥stage1 让渡。全栈回归 ALL SUITES GREEN。

* fix(session): 酒/火两通道真数据校准 + 扩展版本跟随主版本(0.0.1-rc.N)

为什么:上两个提交的酒/火通道带着「公开常识口径,首个真会话后校准」的已知
限制——founder 指示 todo 要自己跟进。本轮不用真会话就完成了大部分校准:
全部用官方/一方数据源,真错在首查前被抓掉。

- 12306 电报码表:自官方全量站表(station_name.js,3384 站)逐条校准——
  **纠出南宁 NIZ→NNZ 真错码**;扩到 129 城(含丽江/大理/香格里拉/拉萨等全部
  热门目的地);核对快照落 data/stations-12306-verify.json,测试逐条锁定
- 12306 座位桶索引:**第一方校准**——自官方前端 queryLeftTicket_end_js.js 的
  cN(result,map) 转换函数逐字段提取。旧公开常识索引(19-28 段)与官方现行
  映射全错(站名不在 15/16,而是 data.map[电报码];座位桶实为 20-33 段,
  gg/gr/qt/rw/rz/tz/wz/yb/yw/yz/ze/zy/swz/srrb)——原解析遇真回包会整行
  签名失配,首查必 miss,本轮提前修复;测试用下标探针行锁官方映射
- 携程酒店城市 id:探测法 + list 页 <title> 逐条验证(曾纠出 104=平遥县、
  14=苏州 等 5 处错猜——猜测直接进表会是数据灾难),实测 35 城入表,含
  **迪拜=220**(轨迹里 agent 构造的 id 正确)、丽江=37、大理=36、三亚=43
- 携程接口/形状:接口路径一方确认 restapi/soa2/34951/fetchHotelList(URL hint
  + content-main 嗅探面同步);解析器加「hotelInfo 包裹」结构化通道(SSR 实测
  形态:nameInfo.name/hotelStar.star/commentInfo.commentScore + 价格子树探测),
  通用走形兜底不变
- 版本跟随主版本(founder 拍板):manifest version_name = package.json 原样,
  version = 四段投影(0.0.1-rc.N → 0.0.1.N,Chrome manifest 只收点分整数);
  dist-manifest 校验放开 1-4 段;§38 加版本跟随防漂移断言
- 扩展 0.0.1-rc.18 已落位 ~/.gotry/extension(四站点注入),用户 Chrome
  chrome://extensions 里点一次重载即生效
- 测试:session 107/107(电报码防漂移/官方索引探针/真实形状 fixture)+
  §38 28 段(版本跟随)+ distribution 36/36;全栈回归 ALL SUITES GREEN

* docs: 企业级差旅 Agent 系统八维参考研究——借鉴决策落到 M5/M6 既有接缝

为什么:founder 提供某企业级差旅 Agent 生产系统与 gotry 的八维对比分析
(来源脱敏),需要把「学什么、学到哪个里程碑、不学什么」固化为仓内决策面,
防止后续 agent 重复调研或被带偏差异化。

结论速览:双轨执行/写闭环三机制(sealed interface/pending 持久化/写边界
分离)→ M5 Entry checklist(ADR-17 边表+RFC S4 已同构,不提前写代码);
合规收口装饰器/领域 skill 封装 → M6 设计输入;生产级状态面 → D-15
触发器纪律不变;双模型分级/上下文压缩 → 不采纳(ADR-24 确定性路由 +
slot-spec 已覆盖同问题);事件驱动增量渲染 → Booking Copilot v2 typed SSE
已是同构面,不新增机制。对 v0.0.1 无阻塞项。差异化(Z3/证据链/全成本/
愿望池)保留清单与「不追求代码量等价」判定一并固化。

保鲜清单勾稽(§11,非 M-exit):纯文档,①-⑥全部让渡(无形态/状态/债务
变化);§12 文档地图已同步注册。

* docs: 状态面版本漂移修复——npm latest=rc.18 同步进 roadmap/README 三处

为什么:rc.17/rc.18(2026-09-02 已发,registry time 实测)发表后状态面
未同批同步——roadmap 发行状态停在 rc.16、rc 序列表缺两行、README 中英四处
版本基线停在 rc.16/rc.17,与 registry 实态(latest=rc=rc.18)不符。§11 纪律
要求状态面与现实同步,本提交补齐并记入回拉实测证据(2026-09-03 干净安装
559 包/bin --help/dist 入口全通)。

保鲜清单勾稽(§11,非 M-exit):①§1 让渡(无版本数字);②§9 让渡(发行叙事
归 release-notes/CHANGELOG);③§10 让渡(无债务变化);④roadmap 本提交;
⑤README 中英本提交;⑥stage1 让渡。

* fix(session): 携程酒店价格路径第一方校准——roomInfo[].priceInfo.price

为什么:上一提交把酒店价格字段留作「等首个真会话终验」——不需要等:接口直连
复现虽被 hotel-spider-defence 反爬 404(「让站点自己发请求」正是会话桥的设计
原因),但官方前端是公开静态资产,顺 webpack 运行时 chunk 映射逐个反查,list
页 bundle 的响应映射段把价格路径完整写明了。

- 官方路径:条目 = hotelList[].hotelInfo{summary{hotelId,nameInfo{name,
  names[]},hotelStar{star},positionInfo},commentInfo{commentScore},roomInfo[]};
  明文价 = roomInfo[].priceInfo.price(多房型取最低;页面 room_price 即读此);
  displayPrice 字符串价原样保留(打码口径);酒店名主路径 nameInfo.names[0]
- 加密价红线:priceToken 在而无明文 price = fetchHotelListPrices 解密链路的
  加密态,解密发生在页面内存,嗅探面天然拿不到——条目保留(名/星/评分照常),
  价如实为 0,不伪造任何数字
- 解析器:结构化候选按官方路径重写(roomInfo 优先 → price/amount 族子树探测
  殿后);通用走形兜底不变
- 测试:session 110 pass(多房型最低价/加密价不伪造/displayPrice 打码 三组
  新 fixture)+ §38 28 段 + smoke OK;全栈回归受影响面全绿

* docs: 存量参考来源脱敏——内部差旅系统统一改称「T 系统」

为什么:产品设计/总纲等早期文档以真名引用了一套内部企业差旅生产系统
(含归属表述、本地路径、内部文件路径与内部工具名)。公开仓库不应携带
这些指纹。本次将全部存量引用统一脱敏为「T 系统(某企业级差旅 Agent
生产系统,来源脱敏)」——与 enterprise-travel-reference-study.md 的口径
一致;设计决策语义(复用矩阵 bridge/reference 约束、六层 memory 框架、
双执行模式、G5 门)逐条保留,只抹来源标识。

范围:product-design 10 处 / master-outline 21 处 / architecture 1 处 /
memory-design 2 处 / tech-strategy 4 处;vendor(dsh 上游)不动;
已验证零残留(全仓 tracked 文件指纹扫描零命中)。

保鲜清单勾稽(§11,非 M-exit):纯文档,①-⑥全部让渡(语义不变,无
形态/状态/债务变化)。

---------

Co-authored-by: Danceiny <danceiny@gmail.com>
* docs(persona-bench): agent 产品人格横评入册——同一真实行程 prompt 投喂各家 AI(Kimi 13 轮已有复盘、飞猪单轮新增存档),沉淀 G1-G8 评分卡与「两家派生星期同落 2025 年历」同型失败发现,反哺行为契约两条候选缺口;README 双语新增横评面,让产品人格差异可检验、可追溯

* feat(persona): 行为契约横评反哺落地(#121/#122)——(1) 动机先行扩展同行人到达链访谈(见面/汇合类必问,落 gotry_companion_save,分链核算)+ 新增 (22) 到达账必达(红眼/落地即消耗航段显式给到达账,时刻表正确≠行程可行);founder 2026-09-04 拍板,出处 persona-bench G4/G7;行为契约 21→22 条,六状态面同提交同步(arch §1 计数/§9 演进、roadmap 架构面增量、stage1 状态头、bench §7 落地回写)

---------

Co-authored-by: Danceiny <danceiny@gmail.com>
…ob 迁 dsh typed ParameterSchemaSpec 平铺七字段(kind 枚举 required+六可选),模型可见逐字段 JSON Schema+execute 前宿主权校验(ToolArgsError→guardToolExecute 兜 ADR-13 ToolFailure 形状不变);迁移锁 smoke §12+channel-registry-tests §8(legacy blob/枚举外值入口即结构化拒绝);普通模型对参数形状不再靠猜。余量工具迁移与 flyai 普通模型 canary 记 D-30;六状态面同提交同步(arch §9/§10、roadmap 架构面增量、stage1 状态头)。run-all 全栈回归 ALL SUITES GREEN
)——平铺字段模型可见逐字段 schema;hotel(destination required)宿主权入口拒畸形参数,session 三意图无公共 required 保留 interpretArgs 容忍层(blob 归一照走业务闸,smoke 迁移锁钉死零 transport 短路路径);skills-contract 契约对齐(checkOut 字面量进参数描述);smoke/hbcli-e2e/channel-registry/skills-contract 全绿,run-all ALL SUITES GREEN;六状态面同提交同步(arch §9/§10、roadmap 增量、stage1 状态头);余量工具与普通模型 canary 记 D-30
…doctor/artifacts_list/fact_gate/agent_reach/turn_handoff_list/artifacts_read 平铺字段模型可见逐字段 schema;刀法总纲确立:有 required 字段的工具(artifacts_read path)宿主权入口拒 blob,全可选工具保留 interpretArgs 容忍层(doctor-tests blob 调用隐式锁);agent_reach 的 action 不设 enum——反射桥 D-4a' 透传上游新增渠道零改动;fact_gate 的 itinerary 保 object+additionalProperties:true,嵌套收紧归 #118 D-26;累计 11 工具迁移,tsc+smoke 全绿,run-all ALL SUITES GREEN;六状态面同提交同步(arch §9/§10、roadmap 增量、stage1 状态头)
…/anything/web/video/github 七工具 typed 参数契约迁移(issue #112)——trip_log 的 destination/start/evidence required 进 schema,evidence P0 溯源红线由宿主权闸;web_search 字符串 blob 形态退役(smoke §6 改锁宿主权拒绝);github_search 顶层 query 从对象形态变字符串字段;wish_pool 全可选保留容忍层;刀法总纲:required 具备宿主权即拒,全可选容忍层;累计 18 工具迁移,余 feasibility/motivation/companion 三个 payload 形态记 D-30;tsc+smoke 全绿,run-all ALL SUITES GREEN;六状态面同提交同步(arch §9/§10、roadmap 增量、stage1 状态头)
…lity(payload 结构化对象,嵌套权威在 unified 引擎契约不越层强约束)/motivation(profile 闭合对象,evidence P0 反伪造红线进嵌套 schema 由宿主权闸,smoke §1 断言适配宿主权前置拒绝)/companion(闭合对象 label/evidence required,additionalProperties:false 与负面清单同向);刀法总纲:required 具备宿主权即拒,全可选容忍层;evidence 类红线全数进 schema;tsc+smoke 全绿,run-all ALL SUITES GREEN;六状态面同提交同步(arch §9/§10、roadmap 增量、stage1 状态头);余量仅普通模型 canary(过闸才进发布面)记 D-30
…ingHeadline:七个检索工具描述前置注册表生成的「服务意图 × 通道顺位(证据级降序)」卡,选工具与失败改道两决策点同表,注册表加行描述自动一致,非检索工具零误伤;②doctor 补齐 patch 宿主插件 dsh-map-tools/dsh-tool-ask-user 两态(解析失败整块静默剔除不挡启动,此前无人知),候选清单与 bin 解析同口径;实测暴露 source 布局 map-tools 全布局缺席(地图工具一直被静默丢弃),补依赖渠道留 founder 拍板;调试副产物:apply() 进程护栏吞异常进 incident 的语义被测试流程踩实(断言失败须读事故文件定位);channel-registry-tests §7/§8+smoke+doctor-tests+skills-contract 全绿,run-all ALL SUITES GREEN;六状态面同提交同步(arch §9、roadmap 增量、stage1 状态头)
…er 在 spawn dsh 前以分离子进程后台跑只读体检(gotry-bootstrap.js doctor --summary):待处理项一行 stderr(对话里 gotry_doctor 看详情/终端 npx gotry doctor),全 ok 静默零输出;零 header 零写盘、detached+unref 不阻塞启动、恒 exit 0、benchmark 面豁免保零杂音,inner 生命周期天然一次不重复刷——初始化可见取代会话中段撞错(design §3.1③);bootstrap-tests §10 以隔离 HOME 钉行为(10/10),run-all ALL SUITES GREEN;六状态面同提交同步(arch §9、roadmap 增量、stage1 状态头)
…/agent_reach/session_login 六渠道入效应注册表,23 工具外部依赖面全收敛 effect_interpreter.v1(没有策略表行就没有效应);策略行逐条拍板:ANYTHING 同 HBCLI 族(timeout 瞬时重试 1 次)/WEB_READ 免费公共源族(瞬时抖动重试+熔断)/GITHUB·VIDEO(verdict=timeout 重试,not-installed 配置态不重试)/AGENT_REACH 反射桥透传永不重试不熔断(wrapper 不是 router,重试即放大上游配额消耗)/SESSION_LOGIN 浏览器风控族;工具面照旧平铺,证据链逐源标注不变,agent_reach status/reach 两分支收敛单一效应;effect-tests §12 四组断言(入表透传/永不重试族/timeout 重试/mock 同语义)12/12,tsc+smoke 全绿,run-all ALL SUITES GREEN;六状态面同提交同步(arch §9、roadmap 增量、stage1 状态头)
…)——needsExtensionSummary/localExtensionInstalled(extension-bridge):本地 unpacked 落位(~/.gotry/extension/manifest.json 在)保留完整双通道指引;未落位(商店版用户/未装)自动跳过开发者模式/本地通道文案,只推商店一键装+「已装商店版?打开 Chrome 即可」;桥失败摘要(extension-not-connected)同函数同语义;doctor 扩展项 detail 明示商店版用户可忽略本项(以运行时 verdict 为准);extension-channel 静态 NEEDS_EXTENSION_HINT 退役为自适应函数(静态文案无法感知安装状态正是 D-24 残量病灶);extension-tests §38 三条新断言 31 段全绿,doctor-tests 绿,tsc 绿,run-all ALL SUITES GREEN;六状态面同提交同步(arch §9、roadmap 增量、stage1 状态头) (#128)

Co-authored-by: Danceiny <danceiny@gmail.com>
* feat(facts): 事实闸覆盖面——酒店 claim 入闸 + 渲染原语单向生成(issue #118,D-26 收口)——HotelFact 第三形态:exact-date 酒店检索 hit/miss 落账(flyai-hotel/session:ctrip-hotel 接线),摸底不落账/传输失败不落负事实/打码价不落数字价;gotry_fact_gate 酒店 claim 入闸(目的地+档期回溯,无事实 fail-closed unverifiable_hotel_claim,miss 在册写有房=not_in_source);渲染原语单向生成:renderFlightFact/renderHotelFact 行内嵌 fact:<fact_id> 锚点,闸侧锚点优先确定性回溯(启发式让位),手改/伪造锚点=fact_anchor_unknown;policy 窄化断言显式化(FlightFact);fact-gate-tests §10 八断言 56 pass,tsc+smoke 绿,run-all ALL SUITES GREEN;六状态面同提交同步(arch §9、roadmap 增量、stage1 状态头);政策生产端(实时签证 API)仍记 D-26 外部依赖

* fix(runtime): 移除 legacy vendored dsh 回退路径(issue #120,D-27 清偿,决策=移除运行时路径)——selectDshRuntime 只认 root manifest/依赖解析(216 精确依赖闭包),找不到即 fail-closed 报错指重装;决策依据:旧 vendored 形态 Node 兼容窗口已断(D-27/Round 5「不承诺可运行」),解析成功只会把 dsh 缺失变成下游玄学失败;inner vendoredDshEarly/legacy-vendored source 分支/报错文案同步移除,DshRuntime.source 收敛 'root';§48 e2e 断言改为非 benchmark 也不再回退 vendored;vendor 闭包目录不属本清偿范围(锁一致性面另行处置)。tsc 绿,§48 e2e 绿,run-all ALL SUITES GREEN;六状态面同提交同步(arch §9/§10 D-27 清偿、roadmap 增量、stage1 状态头)

---------

Co-authored-by: Danceiny <danceiny@gmail.com>
…lFact 第三形态:exact-date 酒店检索 hit/miss 落账(flyai-hotel/session:ctrip-hotel 接线),摸底不落账/传输失败不落负事实/打码价不落数字价;gotry_fact_gate 酒店 claim 入闸(目的地+档期回溯,无事实 fail-closed unverifiable_hotel_claim,miss 在册写有房=not_in_source);渲染原语单向生成:renderFlightFact/renderHotelFact 行内嵌 fact:<fact_id> 锚点,闸侧锚点优先确定性回溯(启发式让位),手改/伪造锚点=fact_anchor_unknown;policy 窄化断言显式化(FlightFact);fact-gate-tests §10 八断言 56 pass,tsc+smoke 绿,run-all ALL SUITES GREEN;六状态面同提交同步(arch §9、roadmap 增量、stage1 状态头);政策生产端(实时签证 API)仍记 D-26 外部依赖 (#129)

Co-authored-by: Danceiny <danceiny@gmail.com>
…face contract (#133)

* refactor(booking): converge to single booking.surface contract

Merge the v2 stack into the canonical file names and delete the v1-only
runtime: contracts/runtime/server/validation are single files, the v2
availability policy becomes availability-policy.ts, and startup/dsh-planner
lose the dual runtime/planner factory seams. All exported identifiers drop
their V1/V2 suffixes, BOOKING_SURFACE_SCHEMA_VERSION is 'booking.surface',
BOOKING_SURFACE_SCHEMA_SHA256 pins 29b2bf11..., and the single handshake is
enforced on one HTTP path. canonical-schema.js reads only the canonical
schema (no cross-file $refs), the dsh plugin projects it directly, and the
ledger family drops its version vocabulary. Retired v1/v2 schema files are
removed; JSON wire field names are unchanged.

* test(booking): port booking copilot proofs to the single contract

Promote the v2 proofs to canonical names (booking-copilot-runtime,
booking-surface-contract, booking-copilot-availability-policy), delete the
v1-only proofs, and rewrite the crossrepo fixture server on the merged
runtime/server with the booking.surface handshake. Concurrency proofs
(receipt/operation/event-sequence) now run against the durable single
runtime; server/startup/dsh proofs use the flattened composition. All
retained proofs pass with exit 0.

* build(booking): pin release artifacts to booking.surface + schema sha256

package.json exposes the single canonical schema subpath and drops the
v1/v2 export twins; the release builder and its proof pin SCHEMA_VERSION to
booking.surface, SCHEMA_SHA256 to 29b2bf11..., verify only the canonical
schema bytes, and expect the single-handshake health contract with a 409 for
retired handshakes. run-all-tests.sh references the retained proof set.
…nStack react-virtual 嵌套条目)缺失导致的 npm ci 严格校验失败(#133 收敛后 lock 未再生,CI 全红根因)
The lockfile regenerated in 45b0958 recorded bnpm.byted.org resolved
URLs, which neither GitHub runners nor the UAT build host can resolve.
Same artifacts, same integrity hashes — only the mirror host changes.
fix(ci): point package-lock resolved URLs at the official registry
# Conflicts:
#	README.md
#	README.zh-CN.md
#	bin/gotry-bootstrap.js
#	bin/gotry-inner.js
#	cordis.gotry-patch.yml
#	docs/architecture.md
#	docs/roadmap.md
#	docs/stage1-top-down-design.md
#	ts/capabilities/doctor.ts
#	ts/scripts/bootstrap-tests.ts
#	ts/scripts/effect-tests.ts
#	ts/scripts/smoke.ts
#	ts/src/index.ts
@Danceiny
Danceiny merged commit 0ce4e8d into feat/session-hotel-train-doctor Sep 4, 2026
3 checks passed
@Danceiny
Danceiny deleted the stack/d30-115 branch September 4, 2026 21:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant