工作台总设计 · 附录 C · 酒店库能力盘点(luxing-kb)
~/luxing-kb(ddl / tools / docs / ops / data 文件名)后的盘点,未连库、未开凭据。仓库真源 LX01
~/luxing-kb(git);数据 ~/luxing-kb-data;生产库 PostgreSQL 17 luxing_kb。库结构(schema/ddl.sql,v3.4 s2 + b27 + b28)
71 表 · 19 视图 · 29 函数 · 150 条 COMMENT(v_data_dictionary 可直接驱动自描述表单)。
五个承重不变量(Web 不得违背):I1 身份自铸(property/room_type 主键我们生成)· I2 观测只增("当前"永远是推导)· I3 金额精确(BIGINT 最小货币单位 + 币种成对,查 currency_unit)· I4 口径不齐拒绝相减(算不出就 NULL + 原因)· I5 否定可存(判过"不是"、查过"无房"都是知识)。
| 域 | 表 | 要点 |
|---|---|---|
| 治理 | row_history currency_unit audit_event vocabulary reject_code schema_version | audit_event.actor_kind=AGENT 给 LLM 执行者记账;vocabulary 是 agent 生成查询前第一读物;reject_code 只录有执行者的码 |
| 身份(13) | business_entity channel destination property property_alias property_relation building room_type meal_plan tag_category tag property_tag room_type_tag | property.status(CANDIDATE/ACTIVE/PAUSED/CONSULT_ONLY/ARCHIVED);collection_interval_hours(24/72/168/720/NULL);adult_only / room_type.private_bath_onsen NULL=未核实必须与"确认不是"区分 |
| 渠道观测(2) | src_listing src_room | 渠道改 ID→新行;复用旧 ID→epoch+1;lifecycle ACTIVE/STALE/GONE;property_id 只能由 apply_listing_decision() 写;match_verdict 只有 EXACT 进比价 |
| 匹配判定(2+2) | listing_match_decision room_match_decision (+POI 两张) | 只增,NOT_SAME 也落行;判 DIFFERENT 必须 basis=facet_conflict 硬证据 |
| 事实/契约(4) | tax_rule policy_term channel_agreement contact | tax_rule.calc=NONE 表达"确认无此税";collected IN_PRICE 进比价 / AT_PROPERTY 只进提醒;policy_term.authority REFERENCE/CONTRACTUAL/OBSERVED,报价只许引用后两者;channel_agreement.credential_ref 指外部密钥 |
| 知识(6) | source_document evidence_fragment assertion assertion_evidence knowledge_chunk media_asset | authority_tier 1-5;citation 能"打开到那一行";polarity=DENIES 是有证据的否定;knowledge_chunk 全库唯一允许 DELETE |
| 观测流与现价(6) | ingest_batch price_observation availability_observation channel_quote fx_rate stg_offer | price_observation 按月分区无 DEFAULT 分区需每月预建;price_unit 默认 UNKNOWN;price_basis GROSS/NET/PARTIAL/UNKNOWN;source_fingerprint 九列 sha256 = 采集侧 OFFER_KEY |
| 交易(6) | quotation booking commission_rule points_rule settlement booking_ledger_evidence | quotation JSONB 快照 + content_hash 触发器 + 锁定后仅 status 可流转 + citations 溯源;booking.confirmation_code;points_rule.program_kind GROUP_LOYALTY vs OTA_POINTS 绝不同列比较;booking_ledger_evidence 一行=一份确认函里一个酒店子订单=成交候选,不证明履约 |
| 囤房(3) | inventory_batch inventory_unit inventory_hold | batch 无计数列占用现算;cancel_deadline NOT NULL 是生死线;unit 一间=一个予約番号挂某会员账号;name_change_allowed 决定能否转客户;触发器逐晚不超卖 |
| 监控/自动化(2) | monitoring_task automation_rule | 刷房+刷票统一;AUTO_BOOK 规则必须挂 capability_envelope |
| Ops 三段式(6) | capability_envelope action_intent action_approval action_attempt effect_receipt action_reconciliation | 封套三上限 NOT NULL;intent CREATED→READY→DISPATCHED→{SUCCEEDED,FAILED,UNCERTAIN},UNCERTAIN 一等状态;worker 200 只是 outcome_note;effect_receipt 唯一能证明外部世界发生了什么,BOOKING_CREATED 必须带确认号;对账 DUPLICATE/MISSING 一等状态 |
| POI 供给(15) | poi poi_alias poi_offering src_poi_listing src_poi_item poi_match_decision poi_item_match_decision poi_price_observation poi_quote poi_inventory_batch/unit/hold poi_booking poi_tag stg_poi_offer | 照抄酒店域纪律;poi_offering.audience 让大人票/儿童票成为不同商品;transferable 是命门 |
视图(19 个,Web 主要读口,全部无参、全部带 COMMENT)
| 视图 | 一句话 |
|---|---|
v_price_comparable | 同口径比价面,统一到 GROSS;七类拒算 |
v_quote_unit_conflicts | 同一商品多计价单位并存=采集矛盾面,非空则相关结论不可采信 |
v_at_property_taxes | 到店付税提醒(销售话术出口),verified_at IS NULL 表示未核实 |
v_inventory_remaining / v_poi_inventory_remaining | 囤房/囤票逐晚剩余,现算 |
v_poi_price_comparable | 供给点比价面 |
v_deadlines | 现金风险雷达(房+票统一),运营每日第一张表:ALLOCATION_CANCEL / HOLD_EXPIRY / POI_* / QUOTE_EXPIRY |
v_collection_due | 采集到期作业单:饥饿度=超期倍数,从未采过排最前 |
v_ingest_errors | 灌入失败行唯一出口,修复后重跑即重试 |
v_match_queue / v_match_exclusions | 匹配工作队列 / 每对最新判定(NOT_SAME 禁再提案) |
v_property_coverage | 覆盖度看板,"失去一条渠道"一眼可见 |
v_data_dictionary | agent 自描述入口;description NULL = 缺口刻意可见 |
v_citable_assertion | AI 可引用知识面:VERIFIED + 有 SUPPORTS + 有效期内 |
v_knowledge_conflicts / v_knowledge_polarity_conflicts | 冲突队列,人裁决 AI 不选边 |
v_booking_ledger / _by_property / _unresolved | 确认函账本口径;cny_reference_total 不是收入;unresolved = 建实体/补别名优先级 |
函数(17 可调用 + 12 触发器)
可调用:ingest_stg_offers(batch) · ingest_stg_poi_offers · promote_observation(obs, captured_at)(观测→现价唯一晋升路径,时序保护)· promote_poi_observation · apply_listing_decision / apply_room_decision / apply_poi_decision / apply_poi_item_decision(SECURITY DEFINER,仅 kb_curator)· inquiry_evidence_card(property, stay, adults)(询单证据卡:酒店×入住日×人数一站式事实面,每项带采集时间与证据指针,缺项进 unknowns)· applicable_tax / applicable_tax_poi(PROPERTY > CITY > PREFECTURE > COUNTRY)· child_price_total(分档非法→NULL,空数组不是通行证)· offer_fingerprint(九列)· ensure_month_partition(须每月预建)· child_ages_sig · quotation_content_hash · parse_bool。 触发器:touch_updated_at · capture_row_history · enforce_tag_level · quotation_guard · check_hold_capacity / check_poi_hold_capacity · enforce_intent_gate(进 READY 核封套七项,SUCCEEDED 必须有回执,日限额含 FAILED)· cascade_envelope_revoke · enforce_recon_gate · downgrade_unverified_assertion · guard_doc_supersede · deactivate_superseded_doc。
角色
kb_reader 只读(AI 与 Web 只读页默认)· kb_ingest 只写 staging/观测/判定提案 · kb_curator 身份/事实/知识/判定生效 · kb_trade 报价/订单/囤房/Ops。apply_*_decision 对 PUBLIC REVOKE,仅 kb_curator。
拒绝码与可比价规则
| 码 | 为什么拒 | 怎么修 |
|---|---|---|
NO_ROOM_IDENTITY | 价格没有房型身份 | 补房型匹配 EXACT |
MATCH_NOT_EXACT | 判定为 FAMILY/DIFFERENT/UNKNOWN | 复核判定 |
CHILD_PRICING_UNKNOWN | 含儿童但无分档 | 补 child_breakdown |
PRICE_UNIT_UNKNOWN | 计价单位未声明 | 补 channel.offer_price_unit 或行级声明 |
PRICE_BASIS_UNKNOWN | 含税口径不明(PARTIAL 同等拒算) | 核实渠道口径 |
CONSUMPTION_TAX_RULE_MISSING | 缺消费税率 | tax_rule 录入(含出处) |
SERVICE_CHARGE_RULE_MISSING | 缺服务费税则,不按 0 猜 | 录费率或 calc=NONE(须带出处) |
OFFER_STALE | 超渠道 TTL | 重采 |
NO_PRODUCT_IDENTITY | 供给价格无可售项身份 | 补匹配 |
HEADCOUNT_ZERO | 每人价但人数 0 | 补人数重灌 |
Web 应直接读 reject_code 表渲染"为什么不能比 + 怎么修",不在前端硬编码。 换算:TOTAL_STAY→amount;PER_ROOM_NIGHT→×rooms×nights;PER_PERSON_STAY→×adults + child;PER_PERSON_NIGHT→(×adults + child)×nights;NET→×(1+服务费)×(1+消费税)。comparability_key = property|room_type|meal|adults|children|rooms|currency|stay_range,只有 key 相同才可比;跨币种在业务层用 fx_rate。到店付税永不参与比价。 price_unit 契约:IKYU/RAKUTEN/JALAN/JAPANICAN/PRO489/TRIPLA/MARRIOTT_WEB/IHG_WEB/YAHOO_TRAVEL/RURUBU = TOTAL_STAY;NTA/DRESERVE/KNT = PER_PERSON_STAY(每人价随人数递减,1 人价不得 ×2);RELUX/HILTON = UNKNOWN(拒算);GDS_MAIN price_basis_default=NET。channel.quote_ttl_hours 是现价采信期。 旧契约(docs/handover/数据契约.md):采集侧 SQLite offer 宽表 comparable=1 唯一比价入口,price_2adults 唯一读数列,hotel_uid_source 只有 xref/content_strong 能跨平台聚合。
工具能力清单(shared/tools/,约 60 脚本;[冻结] = 只新增不修改)
抢房链:snipe_center.py[冻结](秒级轮询·安全判定·拼链·分发,零模型)· snipe_probe.py[冻结](便宜探针+每请求换 IP)· snipe_worker.py[冻结](零决策执行器)· kuku_probe_dispatch.py(TX 采集端 v2:日历直读→房型细查→拼深链→广播 kuku_workorders.jsonl + 心跳)· kuku_probe_pool.py(手工工具)· kuku_calendar.py(「日付未定」日历直读,放房主信号)· kuku_autodispatch.py(三机常驻派单守护 v2:ssh tail 工单→匹配排班→租约→并发下单→告警注入分队 AI)· kuku_yahoo_book.py(雅虎/一休下单执行器,五条硬护栏写进代码)· kuku_snipe_orchestrator.py · kuku_machines.py(seq↔机器唯一映射,真源 ops/deploy/machines.conf)· kuku_watch_status.py(三机+TX+台账一屏健康盘)· kuku_preload.py · kuku_preheat_tabs.py · kuku_conc_drill.py · kuku_confirm_batch.py · kuku_confirm_diag.py · kuku_fufu_observe.py(放房规律观测台,绝不下单)· kuku_fufu_fill.py · grok_ticket.py(挂单状态机+模拟演练)。
采集链(grok_* 契约 v2,全部 fail-closed 住宅代理,只写分库):ikyu(grok_ikyu_run/targets, free_ikyu_seed;GraphQL 前导零)· jalan(Windows-31J;__perPerson+__total 成对)· rakuten · NTA[冻结 nta_*](yadoPlanCalendars 批量门;per_adult_tiered)· KNT[冻结 knt_*](collector/watch/book/verify/retry_watch/register 全链实弹验证)· d-reserve(一月一次日历门)· 489pro · JAPANiCAN · tripla · Relux · IHG(零认证 web key)· Hilton(Akamai SBSD)· Hyatt(Kasada,禁买 solver)· Marriott(CN GraphQL ≤31 天)· 通用:grok_quote.py(统一按需取价)· grok_resolve.py(链接/名字→平台+ID)· grok_archive.py(原文归档+零请求重解析)· grok_resume.py · grok_audit.py · grok_booking_guard.py(read/booking_adjacent/write 三类,write 拒绝)· exits.py(出口供给)· web_session.py · jp_codecs.py · free_* 取证探针。
灌入/晋升:pipeline/load_offers.sh(sqlite→CSV→stg_offer)· pipeline/sync_ingest.sh(拉 TX 分库→load→promote_observation→汇报→作业单回传)· merge_offers.py · apply_patch.py(唯一回填通路,只写 raw_extra)· grok_offers.py(契约 v1:availability≠available → price 必 NULL)。
匹配/比价:grok_resolve.py · cross_channel.py(跨渠道同日期价差)· grok_norm.py(PLATFORM_BASIS 是 channel.offer_price_unit 上游)· render_sales_cards.py(销售版证据卡 v2,底层 inquiry_evidence_card)。
飞书:kuku_feishu_yahoo.py(雅虎台账→囤房登记簿,只新增)· knt/code/feishu_log.py[冻结](基础写入器,绝不 DELETE/PUT)· grok_feishu_hb.py(心跳到非囤房表)。
证据/账本/邮件:grok_holdings.py(持仓台账只读脱敏)· grok_verify_payment.py(付款核验三层判据)· grok_archive.py · grok_watchd.py(统一监控守护)。
Dida:仓内无脚本,属全新接入。
运维:baseline_guard.py · grok_selftest_all.sh · dbq.py · make_packet.py · ops/gen_doc_index.py。
抢房链路端到端(docs/snipe/HEAD-库库-抢房作战.md)
TX 每家酒店一条线程读日历(窗口内 4s / 整点 2s / 平时 15s;9s 未回换 IP 对冲)→ 目标房型×排班日期由不可订变可订=触发(同三元组 rearm 600s)→ 打一次 amounts 拿 planId → 拼深链 → append kuku_workorders.jsonl + 心跳 → 三机守护 ssh tail 续读(15 分钟无心跳自动重连)→ 按 (酒店,住期,房型) 匹配本机 seq 排班→租任务 → kuku_yahoo_book.py --mode submit:BitBrowser CDP → 深链 → BookingInput 填表 → 提交付款 → 每阶段截图 + 予約番号 → yahoo_evidence/ → 台账 append-only(flock)→ 飞书登记(只新增)→ 结果注入分队 AI tmux → 待接 luxing_kb(TX 日历变化已写 calendar_obs_YYYYMMDD.jsonl)。 机器:LX01(生产库+流水线+守护+备份;15 号 30 单)· TX 东京腾讯云(采集机,从不持库凭据)· LG01(守护+异地副本;11 号 19 单)· LM01(守护;18 号 32 单)。 授权 kuku_auth.json(三机各一份):enabled / expires / hotels{id:{checkin_from,checkin_to,price_cap,max_rooms}};auth_check() 纯函数逐条校验;另一前提免费取消(--cancel-ok 必须显式传;页面出现「取消料が発生」拒绝)。2026-09-02 曾因到期静默失效四天。 工单格式:at, hotel, hotel_name, checkin, nights, adults, room_id, room_name, plan_id, plan_name, amount, is_target, link。守护健康 kuku_autodispatch_status.json:armed / bb_api / profiles_alive/total / auth{level,why} / link_age_s / tasks{total,done,inflight,cooling};失败冷却分级;kuku_arm.flag / kuku_disarm.flag。作战窗口每月 30/31/1/2/3 日 07:00–15:00 JST。 坑(Web 必须继承):搜索索引滞后 ≥6 分钟必须读日历;同一 profile 绝不两机同开;BitBrowser API 限流 10 req/s;/browser/close 成功≠进程退出;/browser/list 含代理密码只取 id/name/seq/remark;台账并发写必须 flock;BookingInput p= 令牌不可预构造。
采集链路
渠道 16 + POI 2。节拍:TX cron JST 04:17/16:17 collect_due.sh;LX01 launchd com.luxing.kb.sync 每 6h sync_ingest.sh;每物业节拍由 property.collection_interval_hours 决定。 流:TX 采集器 → offers_<platform>.db + 原文 → LX01 scp 拉 → load_offers.sh INSERT ingest_batch + \copy stg_offer → ingest_stg_offers(batch)(幂等、逐行容错)→ promote_observation 逐行晋升 → v_ingest_errors 出口 → v_collection_due 生成 due_list.csv 回传 TX。 provenance:captured_at · source_url/evidence_ref(指 TX 原文,ops/mirror_tx_raw.sh 每日镜像到 LX01)· source_fingerprint · batch_id · property_id(未解析 NULL,补判后回填,历史不重采);身份剧变靠 epoch 隔离。
飞书表
囤房登记簿列:预定确认号(去重键)· 预定平台 · 酒店名称 · 入住日期 · 退房日期 · 间夜数 · 房型 · 人数 · 餐食 · 日元成本 · 人民币成本(×0.045) · 预订人 · 支付方式 · 售卖、取消情况 · 待人工复核 · 数据来源 · 登记日期 · SEQ · 下单机器 · 备注;条件列 最晚免费取消日 · 建议取消日(-2) · 取消提醒日(-3) · 取消政策原文(取不到整组留空)。 only-append 铁律:只 POST 新增与 GET 查重,绝不 DELETE/PUT/batch_delete;先订完再登记,登记失败不回头影响订房。
运维
部署:git 真源 LX01;ops/deploy/deploy.sh <lg01|lm01|tx> [--restart] 按 git ls-files rsync,远端写 DEPLOYED-REV;verify.sh 四机对比;restart.sh tmux send-keys;link_data.sh;machines.conf(排班真源 SEQS_LX01/LG01/LM01 + TX_HOST/KEY)。 备份 ops/backup_luxing_kb.sh(pg_dump -Fc + sha256 + 异地 lg01 双端比对,本地 14 份,last_backup_status.json);镜像 ops/mirror_tx_raw.sh(只拉不推,无 --delete);ops/db_migrate.sh(每文件一事务→schema_version;24h 内无成功备份则拒绝)。launchd:sync 6h · backup 05:10 · mirror 06:00。migrations 现状只有 0001_schema_version.sql。
决策记录与冻结约束(docs/handover/决策记录.md)
- D1 授权:目标平台均为合作伙伴,采集已获授权。
- D2 价格锚点 = 双人:三种口径锚定双人后收敛;非双人入库但
comparable=0。 - D3 行数不是核心:可维护/可持续/可稳定/标准化四件事。
- D4 只读:采集链禁止提交订单;抢房链已被 2026-08-31 Ling 当面授权突破(免费取消前提),边界由
kuku_auth.json承担。 - D5 不在范围内:HTTP 服务 · 调度平台 · Web 界面 · 可视化看板 · 大规模量产采集。→ 新工作台与 D5 直接冲突,需 Ling 明确解除或改写(9-14 口述已事实解除,决策记录应补 D6)。
冻结:三世界模型 / 观测流 / 渠道单位契约 / 灌入函数 = r3 基座;epoch 分层;append-only 与只增不改;UNKNOWN 纪律;税费种子全部 verified_at=NULL(东京宿泊税 2027-04-01 改定率须换轨);写路径只走函数,裸 INSERT 是绕闸;冻结基线 snipe_*/knt_*/nta_*;schema 改动必须同步 ddl + migration + walkthrough 全绿。
明显空缺(有表无工具/无 UI)
| 域 | 工具覆盖 | 缺口 |
|---|---|---|
| 交易 | 仅 render_sales_cards.py 只读 | 报价签发、订单落库、佣金结算、复购分析全无写路径;quotation 锁定触发器无人调用;v_booking_ledger_unresolved 无处消费 |
| 囤房 | 零工具;下单结果只进本地 json + 飞书 | 最贵的缺口:cancel_deadline 生死线只活在飞书列;v_deadlines 雷达无数据;name_change_allowed 无处记录;不超卖触发器从未触发 |
| Ops 三段式 | 零工具;授权走 kuku_auth.json,回执走证据目录 | kuku_auth.json 四字段正是 capability_envelope 四列;予約番号正是 effect_receipt.confirmation_code——最低成本的一次真源合一 |
| POI | 零采集器/工具/数据 | 食べログ/Klook/官方票务未接;poi.reservation_note 类选品事实无处落 |
| 监控/规则 | 各自状态文件 | monitoring_task 没进库;automation_rule 封套约束无人触发 |
| 知识 | 零工具 | assertion 全空;v_knowledge_conflicts 是为"人裁决 AI 不选边"设计的队列,无入口 |
| 匹配 | 有函数与队列视图 | 无 UI,只能手写 SQL |
| 可用性 | 有表有分区 | rooms_left 与"查过无房"负知识基本没落库 |
真源分裂清单(第一刀方向):① 抢房授权 kuku_auth.json → capability_envelope;② 囤房结果 yahoo_bookings.local.json + 飞书 → inventory_* + booking + effect_receipt;③ 排班 machines.conf;④ 号的裁决 kuku_profile_notes.json;⑤ 抢房目标 kuku_room_targets.json → monitoring_task;⑥ 守护健康 三机状态文件 + TX 日志 → 统一状态端点。
给 Web 的三条落地建议:读侧几乎免费(19 视图无参带 COMMENT,kb_reader 零风险;优先 v_deadlines / v_price_comparable+reject_code / v_match_queue / v_knowledge_conflicts / v_collection_due / inquiry_evidence_card());写侧必须走函数 + 角色(Ops 与囤房触发器已把并发与授权做成结构保证);D5 需 Ling 先行解除。