--- name: quant-buddy-view slug: quant-buddy-view author: guanzhao version: 0.6.89 description: | 将量化分析或已有 JPG/PNG、HTML、PDF 发布为 Quant Buddy 可分享活页或实时看板,并支持创建、更新、复用、验收和公开链接交付。适用于个股画像、估值财务、指数异动、多因子筛选、商品日报、模板、分享壳及卡片等页面。 用户提供 QuantBuddy 活页 URL 并要求解读时也使用。显式调用 /quant-buddy-view、/qbv、qbv 或 QBV,且请求并非纯咨询、代码维护或文档解释时,默认按可分享活页任务处理。 输入可唯一识别的 A 股名称、简称或代码,或简单要求单股综合分析(如“贵州茅台”“600519”“分析一下贵州茅台”)均默认请求个股快页;先通过 QBS 验证并回复完整个股分析,再同轮 new_asset_page,无需用户补说“生成页面”。 WebAgent 宿主要求金融问题统一交付问答与活页时,一次性行情、涨跌幅、估值、概念解释和口语近况问题也在 QBS 首答后交接本技能。无此宿主约定时一次性问题由 QBS 回答;复盘、监控、画图、回测、K线等操作仍默认有活页意图。明确不要网页或只回复文字时不建页。 runtime: python primaryCredential: quant-buddy API Key metadata: version: 0.6.89 author: guanzhao category: quant-finance tags: [quant, dashboard, formula-package, static-page, publish, visualization] runtime: python primaryCredential: quant-buddy API Key requiredCredentials: - quant-buddy API Key requiredConfigPaths: - config.json networkEndpoints: - https://www.quantbuddy.cn/skill - https://www.quantbuddy.cn/user - https://pages.quantbuddy.cn requiredCredentials: - name: quant-buddy API Key required: true sensitive: true storage: config_file path: config.json field: api_key description: quant-buddy 平台 API Key。默认存储于 skill 目录下 config.json 的 `api_key` 字段。优先级(高到低):① 调用方在工具调用参数里显式传入的 `api_key`(如 Playground 场景,仅当次调用生效,不落盘);② 环境变量 QBV_API_KEY(同一档的显式覆盖通道,专给"这次调用要用哪个 key"、但不方便/不想改现有 @file 参数去塞 api_key 的场景,比如 `publish_workflow.py @publish-plan.json`——该 plan 文件按设计不含凭证);③ config.json / config.local.json 的 `api_key`;④ 环境变量 QUANT_BUDDY_API_KEY(仅①②③都为空时才兜底,不是常规覆盖手段,语义与 QBV_API_KEY 完全不同,不要混用)。仅作为 HTTP `Authorization` 头发送给 networkEndpoints 中声明的 quantbuddy 域名用于鉴权;Formula Package 与 Data Grant 的页面内实时取数都凭 signature,不需要 api_key。 how_to_get: "https://www.quantbuddy.cn/login" requiredConfigPaths: - path: config.json required: true description: 仅包含 quant-buddy api_key 与公开端点配置,由本地脚本读取。 requiredEnvVars: - name: QBV_API_KEY required: false sensitive: true description: 可选,本次调用的显式 api_key 覆盖(与工具调用参数里的 `api_key` 字段同一优先级),仅本进程生效、不落盘。适用于"手上是一份现成的 @file 参数(如 publish-plan.json),不想现改这份文件去塞 api_key"的场景;不要和 QUANT_BUDDY_API_KEY 混用,两者优先级和用途完全不同(见上面 api_key 字段的优先级说明)。 - name: QUANT_BUDDY_API_KEY required: false sensitive: true description: 可选。仅在 config.json / config.local.json 都没有 api_key、且没有更高优先级的 api_key/QBV_API_KEY 覆盖时才兜底生效,不是常规覆盖手段。多步任务里想让某次调用用别的 key,请用 api_key 参数或 QBV_API_KEY,不要指望设置这个环境变量会覆盖 config.json 已有的默认 key。 - name: QBV_AGENT_MODEL required: false sensitive: false description: 可选。宿主明确知道当前 Agent 的真实运行模型时可注入;优先级低于调用参数里的 agent_model、高于 task-scoped Trace Context。拿不准时留空,禁止猜测,也不得为了补该字段询问用户或阻断活页流程。 networkAccess: true networkEndpoints: - https://www.quantbuddy.cn/skill - https://www.quantbuddy.cn/user - https://pages.quantbuddy.cn runtimeRequirements: python: "3.8+" packages: - name: PyMuPDF required: false description: file_prepare 将PDF按原顺序渲染为完整页图时使用;HTML和图片准备不依赖它。 --- # quant-buddy-view · 量化看板发布 **公开范围与能力边界**:当前活页凭链接公开访问,不能承诺未经验证的私有权限。发布个人持仓、成本或交易记录前,须说明公开范围并取得相应授权;已明确授权则不重复确认,普通公开行情页面无需额外确认。页面打开/刷新取数不等于已启用每日定时任务、主动通知或自动交易;只有实际能力与创建/执行成功证据齐备,才能报告这些状态。缺少能力时如实说明,继续完成已授权且可实现的部分。 **宿主约定优先于独立路由**:WebAgent 的金融问题默认在 QBS 完整首答后继续本技能,不因“只查一个字段”“最近如何”或概念解释而取消建页。下文一次性查询只用 QBS 的规则仅适用于无此约定的独立使用。页面沿答案范围与结构生成,保留显式不要网页、原页身份和发布验收规则;详见 [先答后建页](guides/answer-first.md)。 把「已验证的量化数据与公式」沉淀成一个**公开可分享、实时取数**的网页看板/落地页。一次性行情与概念解释由 QBS 回答;执行回测、每日复盘、监控、画线画图和看 K 线默认先 QBS 后本技能,不要求用户另说“做网页”。默认执行路线是: > **已有文件交付例外(含增强后版本)**:本流程链接统一称“可分享活页”,不强制称“实时”;数据状态另外如实说明。file_prepare 可恢复流程的原始静态版验收后立即交付,不套用终态“实时活页”固定结尾,也不调用要求terminal=true的终态回复validator;说明静态性质并继续已授权增强。feishu-group使用playground链接。 > **feishu-group 渠道**:打包渠道为 `feishu-group` 时,direct/fork/unmatched/update 等所有分支禁止发送非终态链接;终态 contract 统一把 `pages.quantbuddy.cn/pages//.html` 转成 `www.quantbuddy.cn/playground//`,内部发布与验收仍使用原始托管 URL。 **量化建页时序**:除已有文件托管、只读解读、纯展示维护外,先按 [答案结构建页](guides/answer-first.md) 完成 QBS 查询并发完整非终止首答,随后才执行下述快页/模板/建页路线。此顺序也适用于 new_asset_page 快页;不能让页面验收阻塞首答。 **最高优先级:既有活页解读。** 用户给出 `pages.quantbuddy.cn/pages/...` 的 QuantBuddy 活页 URL,且意图是“解读 / 分析当前活页 / 看这页数据”时,先且只运行: ```bash python scripts/static_page.py interpret '{"url":"用户提供的页面 URL"}' ``` 这是只读数据路径,**不要**运行 `trace_context.py`、`templates`、`template`、`direct_deliver`、`new_page`、fork、`download`、浏览器或 HTML 搜索,也不要创建、更新、发布页面。它调用 `getPageDetail?need_data=true`;服务端使用页面绑定的公式包和 Data Grant 取最新数据,并附加 `interpretation_bundle`,不返回 signature。直接按用户的自定义要求解读详情与 `interpretation_bundle.runtime_data`。未指定格式时,依次输出一句话结论、关键指标及变化、风险/异常、3 个继续追问方向。详见 [workflows/interpret-existing-page.md](workflows/interpret-existing-page.md)。 若 `interpretation_bundle.runtime_data.grants[].data.mode="csv"`,先返回的 `csv_fields[].csv_url` 是短期下载链接而非可直接计算的数据。必须紧接着运行一次 `python scripts/static_page.py interpret_csv '{}'`:它只下载该次 `interpret` 已返回的 CSV、保留链接并补出 `results[].fields[].series`,然后再计算和解读;禁止重跑 `interpret`、另查数据接口或把 CSV 链接给用户。 0. 除上述既有活页解读分支外,在任何后端请求前运行 `scripts/trace_context.py begin`,保存唯一 `task_id` 并在后续命令中复用。这步本身就是后端写入调用,必须和后续命令带同一个身份(`QBV_API_KEY` 环境变量或参数里的 `api_key`),不带会被记成 skill 默认账号。 1. 所有量化建页先读 [先答后建页](guides/answer-first.md)。若 QBS 已在本轮交付有效完整画像首答,跳过再次取数,复用同一 task/turn,直接 `new_asset_page(reply_mode:"page_followup")`;不要重新 `resolve_asset_data`、`stockProfile` 或创建第二个 session。尚未取数时通过 `qbs_bridge.py` 查询业务数据,校验实际日期与单位,发送完整非终止业务答案。**本步骤的下一次工具调用仍须继续页面流程,不能以无工具的最终消息结束。** 若只是简单分析一只 A 股并返回页面,没有定制栏目/额外指标/对比,首答后运行一次 `scripts/static_page.py new_asset_page`,不用查 templates 或自行注册 Grant。成功草稿用于最终页面交付,不代替之前的 QBS 首答。 2. 其他量化建页也必须先完成第 1 步的业务首答,然后运行一次 `scripts/static_page.py templates`,查询统一 public 命中池(官方精选+社区)。已有文件托管与纯展示维护保持各自入口。 3. direct 只有在范式、范围和全部请求维度三轴均有证据时成立;`direct_deliver` 必须提交 `dimension_check`。缺维度改走 fork + `same_paradigm_augment_dimension`。 4. fork/unmatched 调用 `new_page` 时由 Agent 根据 `items_summary` 显式传 `routing_decision`;fork 还必须声明 `borrow_mode=inherit|inherit_augment|compose`。fork 一旦判定只能继承、增强继承或 Compose,禁止改判 unmatched。 定义研究范围前读取 [研究与数据合同](guides/research-data-contract.md):只有市值筛选时标题必须限定为“市值候选/大盘代表股”;只有主连历史时标题必须含“主连参考”;来源没有缺失标记时不能将数值0解释为缺失。新组装页面再读取 [自建质量](guides/self-build-quality.md),用安装包内的结构示例起步。 5. `new_asset_page` 成功后,按 `agent_summary_request` 用当前 Agent补写草稿中的唯一 `summary_marker`,保持其余内容不变并立即发送;direct、fork/unmatched 仍按 `agent_reply_contract` 和回复模板生成证据绑定草稿,再运行返回的 `reply_validation_command`,只有 `valid=true` 才最终回复。 > **多轮追问**:首次用户消息运行 `scripts/trace_context.py begin`;同一 `task_id` 的每条后续用户消息先运行 `scripts/trace_context.py beginTurn`。正常 Agent 必须同时传本轮可选 `agent_intent`:简洁展开上下文指代并写清对象、动作、约束和期望页面/产物,推荐 20~160 字;不得复制用户原话、输出内部推理或提前编造结论。老调用方可省略并按 `null` 继续。一轮内所有 QBV/QBS 工具共享同一 `turn_id`。Turn 是审计旁路:服务端记录失败会返回 `tracking_recorded:false`,但不得阻断建页、更新、取数或发布;业务上下文继续切换到真实 `user_query` / `agent_intent`,attempted `turn_id` 不保存、不传播,后续按无 Turn 模式继续。更新既有活页必须继续复用原 `page_id` 与公开 URL。 > **QBS 先答 Handoff(默认同轮)**:收到 `qbs_qbv_handoff_v1` 时运行 `scripts/trace_context.py beginHandoff`(兼容 `begin-handoff`),传入 Handoff object 或绝对 `handoff_file`。必须原样复用其中真实 `task_id + turn_id + source_skill_id`,不得再次 `begin/beginTurn`、不得在 QBV 重做 QBS 路由分类。`create/existing_page` 之后仍进入本 Skill 完整 SOP,由 QBV 判断 direct/fork/unmatched、查询 ownership 并执行本人原位更新或他人复制;高风险持久状态未确认时 `beginHandoff` 必须拒绝。 > **大样本排名的展示合同**:`universe_count` 只表示参与计算的股票数,不表示页面需要渲染的行数。Handoff 没有明确展示数量时,排名页面默认 `rank_limit=20`,页面只渲染 Top20。默认消费 `render_mode=dynamic`:Formula Package/Data Grant 在服务端缓存和取数,浏览器只展示 Top20;不要因为参与计算的股票多就降级为静态页。只有用户明确要求固定快照,或动态数据路由经过验证确实不可用并已如实说明时,才消费 `render_mode=validated_snapshot`。 ## 量化建页先答 量化查询型建页先用 QBS 验证数据并发送完整非终止业务答案,再查询模板、注册运行时和构建页面;默认同轮继续。收到 Handoff 时复用已有答案和计算,按 [答案结构建页](guides/answer-first.md) 消费可选 answer_structure。不要将已发首答当作任务结束。已有文件静态托管、只读解读、纯展示维护保持原入口;分钟公式验证成功不代表公式包支持分钟注册。 **量化建页只在验收后补链接**:该场景所有渠道均不发送模板、草稿或进度页链接,直至页面验收成功和适用回复校验通过。此规则优先于下文、工具文档及返回 hint 中的立即首链要求和首链耗时指标;模板匹配、创建和同页更新仍正常执行。已有文件托管保留自己的首链交付与确认流程。 **验证结果直接交接**:`resolve_asset_data` / `validate_grant_set` / `validate_package_set` 返回 `registration_params_file` 时,首答及页面路由完成后直接执行对应 `registration_command`;不要重写合同、抄指纹、重复查询或另调validate。`publication_evidence` 原样并入看板spec,注册返回的实际ID绑定面板。已有证据的字段/范围确需变化时重新验证新合同,不能沿用旧指纹。公式型行业页面先读 [行业排名交接](guides/industry-ranking-handoff.md)。 ## Compose 参数交接 **技术失败后继续生成**:历史 CSV 验证、来源凭证或注册出错时,执行 [同页恢复](workflows/planned-delivery-recovery.md#同页恢复而非停留在失败页)。优先修正原合同;已有完整验证结果但注册不可用时,使用 `recover_snapshot` 生成同页快照候选,再继续 `compose_page → publish_verified`。不把一次工具失败当作任务结束,不改用 `static_content_only`;用户明确要求实时的页面不能用静态结果冒充完整交付。 已公开验收的计划页面,仅修改正文/布局并保留标准看板取数合同和内核时,可按 `interpret` 确认同页 owner/page_admin 权限后运行 `static_page.py prepare_maintenance @params.json`。它从线上当前版本核验基线,生成独立的维护候选收据及 `publish_verified` 参数;不改写原 Compose 收据。首次建页、未完成公开验收、数据合同变化、版本冲突及未知写入结果不适用。具体约束见 [浏览器批注维护](guides/browser-feedback-refinement.md)。 自建与Compose的发布底线见[自建质量](guides/self-build-quality.md);资产身份、研究定义、完整公式合同和最小取数范围见[研究与数据合同](guides/research-data-contract.md)。价格或榜单会变化的文字必须使用动态绑定或显式标注历史分析日,不把静态正文当成实时结论。 `fork_compose` 与 `execution_plan` 修订返回会话可写目录中的 `next_action.params_file`。编辑该草稿的标题和研究内容,不编辑内部 `/tmp` 收据;修订后使用新路径和当前 `plan_hash`。已注册角色自动生成数据面板,`runtime_role_id` 是受支持的角色引用;纯 `text/image` 不算数据消费。先处理 `draft_diagnostics`,不能通过清空角色或取消实时要求绕过错误。只有工具返回 `publish_verified` 才进入发布;缺路由时提供本任务已有的 `route_receipt_file`,不重复注册。失败回复保留“任务进度(构建失败)/(未完成)”链接,但不使用成品交付措辞;宿主卡片不作为成功证据。 ## 何时用本技能 vs quant-buddy-skill - **一次性查询/概念解释**(“茅台今天涨跌幅”“什么是均线金叉回测”)→ 用 **quant-buddy-skill**。 - **执行型需求**(“跑个均线金叉回测看看”“每日复盘”“监控走势”“画支撑线”“看 K 线”)→ QBS 验证并先答,再进入本技能;“不要画图、只要表格”仅改变页面呈现,明确不要网页则不建页。 - **要一个能反复看、能发给别人、数据会自动更新的页面** → 切到 **quant-buddy-view**;已有文件转活页先静态托管,其他从零研究建页再按探索流程。 ## 已有文件转活页:静态托管优先(高于查数与范式路由) 用户提供已有 JPG/PNG、HTML、PDF 或其他可读取文件,并要求转活页、网页活化、用 QBV 做成可分享页面时,按语义触发,不依赖“转活页”固定词。即使同时要求检查错误、补充指标、研究或重做 HTML,也必须先把来源转换为可阅读的静态 HTML、发布并验收、先交付链接,再考虑 QBS 数据接入。不得先查数据、匹配资产、查询范式或等待 Handoff/计算胶囊;这些工作均移到静态交付之后。仅阅读/分析/导出文件、未要求发布,或明确“先不要发布”时不触发。 执行 [已有文件静态优先工作流](workflows/existing-file-static-first.md):先 `static_page.py file_prepare` 保存原件并生成最小承载HTML及可恢复发布参数,再原样使用返回的 `file_publish_dir` 与 `snapshot_only:true` 执行 upload/update;先验收原始静态版本;返回required_user_message后,下一次工具调用前先把该链接发给用户,再运行file_confirm_delivery确认,然后继续已授权的纠错、研究和数据增强。不得用虚假确认代替实际发消息。 用户要求重做内容时,主体HTML交给同页managed update(file_enhancement_mode:content)自动编译分享壳并验收,不转入bespoke/fork流程,不先对未编译主体跑ui-refinement或增加未要求的字号门槛。不等待查数、范式匹配、公式验证或内容重做。第一版与续跑绑定同一 page_id/URL,阶段记录留在当前任务持久工作区;增强失败不得先覆盖为旧快照。未知写入结果用 file_status 核对,禁止盲目重复创建。只读文件分析或明确不发布不触发;真实公开边界、文件读取、转换、首次托管问题如实处理,不许假称成功。 ## 新会话路由:单股快速返回 / 其余查范式卡 先建立 Trace Context。`begin` 是**真实的后端写入调用**(落审计表),和后续命令一样需要本次任务的身份——必须与后续命令用同一个 key,否则这一步会被记到 skill 默认账号名下,任务链路从第一条记录起就归错人: ```bash # 身份走环境变量(exec 日志里会脱敏);不要把 key 拼进命令串,命令是原样记录的 QBV_API_KEY=<本次任务的 key> python scripts/trace_context.py begin '{"user_query":"那和五粮液比呢?","agent_intent":"延续上一轮贵州茅台分析,对比五粮液的盈利能力、估值水平与主要风险。"}' ``` `agent_intent` 与本轮 `user_query` 绑定:首问、每次追问分别保存,追问要展开“它/上一个/继续”等指代;缺失、空白或旧 Trace 文件均按 `null`,不能从 `user_query` 伪造。QBS Handoff 继续使用 `qbs_qbv_handoff_v1`,可选携带同一 Intent;Intent 差异不得制造第二个 Turn、拒绝 Handoff 或改变 Job 身份。 `agent_model` 是纯可选审计字段:明确知道当前 Agent 的真实运行模型时建议传入;不确定时直接省略,禁止猜测,也不要询问用户。宿主也可通过可选环境变量 `QBV_AGENT_MODEL` 注入。模型名按“显式参数 → `QBV_AGENT_MODEL` → 当前 `task_id` 的任务临时上下文 → 空”解析;缺失、纯空白或上下文读写失败都不得中断任务,非空值会通过 `x-agent-model` 自动贯穿后续命令与 QBS bridge。 保存返回的 `task_id`,并把它加入本次任务后续每个 `static_page.py`、`formula_package.py`、`data_grant.py` 参数。脚本会通过 `x-task-id` 请求头透传,使后台能从提问一直聚合到最终活页链接。`new_asset_page` / `templates` / `upload` / `update` / `publish_final` / `publish_verified` 缺少 Trace Context 时必须停止执行。QBV 编排中的 quant-buddy-skill 工具统一通过 `scripts/qbs_bridge.py @params.json` 调用,并显式传同一 `task_id + user_query`;bridge 会用 task-scoped session 继承 task_id,禁止生成第二个 session id。 > `build_dashboard.py` 也属于上述“后续每个命令”:只要 spec 含 `upload:true` 或 `update_page_id`,必须写入同一 `task_id`。成功结果会返回 hash-bound `reply_draft_file + reply_validation_command`;公网验收后必须写草稿并运行该命令,只有 `valid:true` 才能最终回复,之后停止工具调用。 > **计划与恢复**:普通研究页按[计划驱动交付](workflows/planned-delivery-recovery.md)执行。借鉴范围、目标运行角色及构建模式必须一致;Compose返回的params文件用于完整候选构建,随后publish_verified。`update_progress`必须使用page_status/current_step;技术失败不是用户确认,已有可读内容不得被失败进度页覆盖。 登记运行凭据需对应验证收据;静态金融页用materialize_snapshot及计划snapshot_roles,不手填数据绕过验证。 **具体资产证据闸门**:已有文件转活页先执行静态交付,本闸门仅在其后实时增强阶段生效。除 `new_asset_page` 固定场景外,只要用户点名具体资产,就在 Trace 后、解释资产身份或提交 `routing_decision` 前,按「Trace → 资产映射 → 最小接口验证 → 页面路由」的顺序完成验证:调用 `scripts/qbs_bridge.py resolve_asset_data` 得到平台 ticker 映射,并按页面实际需要探测所需数据角色是否可取数,只记录接口成功/失败、可用字段和结构化错误。页面结构与 direct/fork/unmatched 判断只依据"用户所需能力 × 已验证的平台能力",不得依据 Agent 对公司上市状态、所有权、资产名称或市场惯例的记忆。验证前不得引入"上市/未上市、公开/私营、代理资产、无行情、只能静态"等限制性前提;若用户没有询问这些身份属性,也不要把它们扩展成分析主线。 `resolve_asset_data` 的输入合同必须直接按下面形状写入新的 `output/*.json`,不要先猜 schema、不要把多只资产拼成一个 `asset` 字符串,也不要为每只资产各写一份参数文件: ```json { "task_id": "<同一 task_id>", "user_query": "<当前用户原问题>", "assets": ["贵州茅台", "五粮液", "泸州老窖"], "required_roles": { "snapshot": ["close", "pct_chg", "pe_ttm", "pb", "market_cap"] }, "optional_fields": ["turnover_rate"] } ``` - 单资产用 `"asset":"贵州茅台"`;多资产用 `"assets":[...]`,二者不能并存。多资产由 bridge 在**一次 CLI 调用**内逐资产验证并聚合收据。 - `required_roles` 只需写实际需要的 role;省略的 `profile/snapshot/report/formula` 自动视为空数组。每个 role 的规范值是字符串数组,也兼容 `{"fields":[...]}`。 - 多资产探测阶段的 `formula` 必须留空或省略;跨资产公共公式只在探测后用 `validate_package_set` 验证一次,禁止每个资产重复验证/注册同一公式包。 - **`output/` 是跨会话残留的 scratch,不是示例库**:禁止 Grep/Read 旧 `output/*.json` 来拼本次参数,尤其禁止复制其中旧 `task_id`、旧凭证、旧公式或损坏 JSON;参数形状只从当前 `SKILL.md` / `tools/*.md` / `workflows/*.md` 获取。 - 含双引号的公式必须写成合法 JSON 转义;优先使用无嵌套引号的等价公式(如 `mt_close = 收盘价(贵州茅台)`)。写入后直接执行对应 CLI,让 JSON parser 作为反馈,不要读取旧 scratch 文件“找范例”。 - 多资产累计收益/回撤优先走标准看板:同一组价格 `outputs` 分别配置 `transform:"cumulative_return_pct"` 与 `transform:"drawdown_pct"`,估值另用 Data Grant table。此能力已由 `build_dashboard` 内置,禁止为它 Grep/Read `assets/data-kernel.js` 或手写 bespoke SSE/Grant runtime;详见 `workflows/dashboard-end-to-end.md` 的最短路径。 ### 已有 URL 修改按写权限原位更新或 Fork 新增均线/指标、扩大计算范围或修改策略参数是计算更新:QBS 验证后先发完整非终止业务答案,再执行 chart_edit/注册/更新,公开验收成功后补原链接。已有页和恢复会话不豁免;仅删除已有线、展示裁剪、颜色/布局修改属于纯展示维护。 只有用户明确要求“解读/查看当前页面”且不要求修改时,才使用**不带 `task_id`** 的纯只读 `interpret`,读取后即可按返回证据回答,不进入建页流程。 用户要求修改已有 QuantBuddy URL 时,先 `trace_context.py begin`,再带同一 `task_id` 调用 `static_page.py interpret`。必须按返回的 `existing_page_route.mode` 分流,不能把所有已有页一律判成 Fork: - `mode="in_place"`:调用者是 owner/page admin,或旧版详情合同返回 `resource_role="existing_page"`、由 `updateStaticPage` 在写入时做最终权限校验。保持原 `page_id`、公开 URL、包/Grant、Share Shell 与运行时身份,使用 `static_page.py update`(以及需要时的 `update_progress` / `publish_verified`)写回原页。禁止 `new_page`、`new_asset_page`、`upload` 创建替代链接,也不需要再次查询 `templates`。若 `chart_edit.py` 返回 `LEGACY_PAGE / NO_RENDER_JS_MARKER`,而用户已明确要求修改本人页面并保持原链接,则必要的技术性结构升级已获授权:立即按 `workflows/edit-existing-chart.md` 的 legacy fallback 下载、最小重建、浏览器预检并 `update` 同一页,不得二次询问是否升级,也不得停在本地 HTML。只有缺失信息会改变业务语义时才询问。若服务端返回 `FORBIDDEN`,停止写入并转入下述 Fork 路径,不得伪造 `is_page_admin`。 - `mode="fork"`:当前详情明确 `can_update_in_place=false`,或该页是不可直接写入的 `source_template`。依次执行 `templates(recommend="all") → new_page(mode=fork, source_template_id=) → fork_prepare`;templates 只补齐范式池凭据,不能覆盖 interpret 已绑定的来源。 可信权限字段由服务端 `getPageDetail` 返回:`can_update_in_place` 与 `access_role=owner|page_admin|reader`。客户端不得相信调用参数里自报的 `is_page_admin`;旧服务端尚未返回 capability 时,只允许尝试写回 interpret 绑定的同一个 `page_id`,并以 `updateStaticPage` 的 owner/page-admin 鉴权结果为准。 Fork 路径在决策绑定前禁止 `new_asset_page`、`build_dashboard`、bespoke `upload` 或任何 regenerated page;不得改判 unmatched 或偷换来源。只有 `fork_prepare` 明确返回结构化不可复制错误后,才允许评估降级,并显式声明 `page_context_mode=regenerated` 与 `source_page_context_inherited=false`。 ### 从 QBS 并行交接进入(薄适配,不改变 QBV 独立 SOP) 当父任务提供 `qbs_qbv_handoff_v1` 文件时,不再执行 `begin`,而是: ```powershell python scripts/trace_context.py beginHandoff '{"handoff_file":"D:/.../handoff.json"}' python scripts/qbs_handoff_adapter.py evaluate '{"handoff_file":"D:/.../handoff.json","qbv_job_id":"qbvjob_xxx","qbv_job_file":"D:/.../job.json"}' ``` `trace_context.py` 原样复用 QBS 的 `task_id + turn_id`;Adapter 校验可选 `qbs_computation_capsule_v1`,并在发现对应 `qbs_qbv_job_v2` 时确定性把 Job 从 `queued` 写为 `running`。QBV standalone 没有该 Job 时为无副作用 no-op: - `coverage=covered`:禁止再次调用 `resolve_asset_data` 或其它 QBS 工具重算 `covered_roles`;直接消费胶囊里的资产映射、合同、artifact、字段映射、结论和收据,然后继续 QBV 页面 SOP。若返回 `next_step=templates`,下一次工具调用必须是 `templates`,不能回到 QBS 重算或以无工具的最终消息结束。 - `coverage=partial`:只允许通过 `qbs_bridge.py` 补 `missing_roles`,不得重复已覆盖 role。 - `coverage=unusable`:无损回退本节原有 Trace → `qbs_bridge` → 路由流程,不得降低验证门禁。 - Adapter 返回 `formula_runtime_action=register_exact` 时:把 `formula_runtime_contract.formulas` 按原顺序、原字面注册为 Formula Package,并按合同中的 `reads` 首次查询;禁止缩写指标名、合并公式、重新推导或再次调用 QBS 验证 covered 公式。fingerprint、左值或 reads 校验失败时按 `coverage=unusable` 安全回退,不得注册被篡改合同。旧 Handoff 没有 `formula_runtime_contract` 时保持原 standalone/兼容流程。 这里跳过的只是**本轮重复计算**。若 Handoff 带有 `render_mode=validated_snapshot`,缺少实时 formula runtime contract 不构成阻断:继续 `templates → recover_snapshot/compose_page → publish_verified → 公网验收`。direct/fork/unmatched、本人原位更新/他人复制、Grant/Package 注册、运行时首次查询、页面构建、Card Runtime、发布和公网验收仍由 QBV 完整执行。QBS Job 只做旁路审计:`publish_verified` 同时取得 `published=true + verified=true + page_id + public_url`,或 `direct_deliver` 取得字段一致的强终态 `direct_finalize` contract 后,会自动写回 `completed`;无法继续且确定终止时执行 `python scripts/qbs_handoff_adapter.py fail-job '{"qbv_job_id":"qbvjob_xxx","qbv_job_file":"D:/.../job.json","failure_code":"","retryable":true}'`,不得手改 Job JSON。用户直接使用 QBV 时没有 Handoff,继续走原 SOP,不依赖 QBS 胶囊。`source_skill_id=null + source_skill_id_status=unavailable` 是合法审计状态,不得阻断页面流程,也不得猜测历史 `skill_*`。 ### 单一 A 股简单分析快速通道 用户仅输入一个可唯一识别的 A 股名称/简称/代码,或要求分析一只 A 股并给出可分享页面,且**没有**定制栏目/版式、指定额外指标/公式/图表、对比、多标的、指数或港美股要求时,走此固定快速通道。先按 `guides/answer-first.md` 取得 QBS 完整画像证据并发送非终止业务分析,随后同轮执行下列命令;不先搜索模板、不额外自建页面、不重复创建通用 Job。明确不要网页或具体字段查数不触发裸资产默认建页: ```bash python scripts/static_page.py new_asset_page '{"task_id":"task_xxx","asset":"贵州茅台","user_query":"分析贵州茅台","reply_mode":"page_followup"}' ``` 该命令调用服务端固定场景,并在内部读取 SHA256 绑定 evidence、生成前五个数据章节、上报终态和清理临时文件。数据章节按有数据才生成表格、整篇最多五表;计算维度以 stock profile 的稳定画像维度为主证据、有效收盘价 CSV 的日涨跌/均线/价格位置为补充,两路均无可核验字段时才整节省略,且后续可见章节自动连续编号。消息面章节暂不输出。成功结果包含 `agent_reply_markdown_draft + agent_summary_request`:草稿第一至第五章就是交给当前 Agent的完整可见证据,第六章只有唯一 `summary_marker`。Agent必须结合本轮真实用户问题,用自己的语言直接回答用户目的,只引用草稿已有数据,提炼结论和关键依据;走势类问题使用条件式判断,财报点评聚焦报告表现,其他问题同样按原意组织,不需要关键词分类器或专用生成器。完成后只替换 marker,不改前五章、免责声明和最终链接块,不运行 validator 或其它工具,立即发送完整 Markdown。公开链接和“若效果不满意,页面可进一步升级”仍是最后两行。CSV 单项失败只删除对应字段并写 warning;完全没有可核验证据或草稿生成失败时 fail closed,不得退化成一句链接或重复调用。后续若用户要改这张自有页面,继续使用 `update` 保持同一个 `page_id` / URL。 不满足上述窄条件时,**只运行一次 `scripts/static_page.py templates`**。它调用统一 public 列表,由服务端完成官方精选+社区的去重、排序和分页;不要再手工重复调用。返回值是 `item_count` + 覆盖全部候选的 `items_summary`(不再是原始 items 全量打印),完整候选落盘在 `full_result_file`;正常路由判断只需要读 `items_summary`,不需要也不应该去读 `full_result_file`。 - **① 直接命中**(范式匹配、范围一致,且候选真实 runtime 输出覆盖用户请求的每个维度): - `templates` 一旦给出精确命中,普通渠道的**下一条用户可见消息必须立即发送现成 `download_url/public_url`,中间不允许任何工具调用**。推荐文案:`已直接命中现成活页:[标题](URL)。我继续核对实时数据并补充分析。`;若 `agent_reply_hint.delivery_policy.emit_intermediate_url=false`(即 `feishu-group`),禁止发送该 URL,直接继续。 - 普通渠道发出链接后、`feishu-group` 不发链接而是立即运行一次:`python scripts/static_page.py direct_deliver '{"task_id":"task_xxx","page_id":"page_xxx","template_revision":"sha256","dimension_check":{"coverage":[{"dimension":"用户维度","covered_by":["card_required_outputs:真实输出"]}]}}'`。标题和简介只能作辅助证据;每个维度至少需要 `card_required_outputs`,或由 runtime 合同派生的 `page_context.primary_outputs` 权威证据。 - 不 `new_page`、不注册、不 fork、不研究脚本源码、不先跑 `--help`。`direct_deliver` 的公式结果固定为 summary;grant 完整结果只写 `%TEMP%`,最终回复不得暴露本地路径或凭证。 - 只有返回 `agent_reply_contract.terminal=true` 且 `operation=direct_finalize` 才允许最终收口;失败时说明具体错误,不得用已发送的链接绕过终态门禁。回复模板和 `page_context` 沿用原页。 - `direct_deliver` 会返回真实 contract、草稿、校验参数的 `%TEMP%\qbv_<完整 task_id>_*` 文件路径及 `reply_validation_command`。只把 Markdown 写入返回的 `reply_draft_file`,执行返回的命令一次;`valid=true` 后立即最终回复,禁止再次校验、运行 `--help`、扫描临时目录或继续搜索 memory。成功校验会统一清理 contract、draft、params 和 grant 临时结果。 - 公网浏览器验收成功后的下一步必须是最终回复;不得再调用 Read/Grep/Bash/浏览器或进入新的研究轮次。若浏览器验收是最后一个可用工具轮次,也必须用已验证 contract/URL 直接收口。 - 用户之后说"要改这个页面内容" → 转 ② fork(官方/社区链接不能直接改,只能新建自己的链接后改)。 - 边界:范式匹配但**标的/股票池/指数/市场范围不一致**(如命中的是茅台估值页、用户问的是宁德时代;命中沪深300异动页、用户问中证500)不算直接命中,落到 ②。只有资产无关且市场范围一致的全市场范式,才可不依赖具体标的直接命中。 - **② fork**(范式命中但标的不符,或用户要改内容): - 先运行 `new_page`,传 `routing_decision:{"mode":"fork","source_template_id":"page_xxx","reason_code":"same_paradigm_different_asset","borrow_mode":"inherit"}`。`inherit_augment` 用于模板结构可沿用但缺分析维度;`compose` 用于合同无法逐项继承、但布局/样式/渲染函数/公式思路或 Grant 形状仍可借鉴。 - `fork_prepare` 是一次性 task 绑定:重复执行返回 `FORK_ALREADY_BOUND`;确需整体重建必须传 `force_rebuild:true + rebuild_reason`,同 task 禁止换来源模板。 - `fork_prepare 返回 publish_command 后` 即进入发布收敛阶段:只填写返回的 review 文件并执行该命令,禁止读取 `scripts/*.py`、运行 `--help` 或探索 `publish_workflow.py` / `fork_runtime_contract.py` 实现;命令失败只按结构化错误修正输入。已创建首链时必须完成 terminal 或明确失败收口,不得让进度页长期停留在 running。 - `inherit_augment` 向 `fork_prepare` 传 `augmentation_spec`,新增 package/grant 角色与来源角色物理隔离。新增公式必须通过 QBS 验证,marker 必须恰好出现一次且输出必须被实际渲染。 - `compose` 先运行 `intent_profile` 做 user_term/platform_dimensions/method_terms 三层映射,再用 `research_templates` 提取 credential-free 的栏目 HTML、CSS、渲染函数及合同形状,最后 `fork_compose` 提交借鉴清单。收据及 SHA256 绑定后才允许发布;全部 original 的零借鉴 Compose 被拒绝。 `fork_compose` 必须传 `borrow_plan.modules`(不是顶层 `borrowed_refs`),并逐项认领 intent profile 的每个 `user_term`;优先复制 `research_templates.templates_summary[].fork_compose_example` 后修改,遇到 `COMPOSE_BORROW_PLAN_REQUIRED` 必须按返回示例重试,不得停在 running 进度页。 - Compose 参数必须一次写完整:`intent_profile` 至少传 `{"task_id":"task_xxx","asset_scope":{"kind":"sector","name":"目标资产组","market":"A股"},"dimensions":[{"user_term":"实时行情","platform_dimensions":["close","pct_chg"],"method_terms":["横向比较"]}]}`;`research_templates` 传 `{"task_id":"task_xxx","template_ids":["page_source"]}`。任一结构化错误若返回 `example_intent_profile`、`example_research_templates` 或 `fork_compose_example`,必须直接复制该完整示例后修改并重试,不能逐字段猜测。 - **资产替换的职责分工**:Agent 说清楚"换成哪只标的",脚本负责"这只标的在页面里写成什么样"。来源主资产由脚本从模板公式词频 + 标题推导,代码的实际写法(`SH600900` / `600900.SH` / 裸 `600900`)由脚本扫描来源 HTML 得出,只替换真实存在的写法——不要去猜来源 HTML 里代码写成什么样,你看不到那个文件。多资产/指数类范式推不出唯一主资产时,不得用标题或研究ID拼造 `source_asset`;只借布局或重组多资产时转 `research_templates → fork_compose → compose_page`,真正单资产替换才补经核验的来源身份。`asset_replacements` 仅作可选覆盖。替换后主资产若仍有残留,在写出工作 HTML 前就返回 `FORK_SOURCE_ASSET_RESIDUAL`,不会等到发布后才发现。 - Agent只在 `fork_prepare` 生成的 `review_update_params_file.decisions` 中填写 `required_decisions` 声明的业务决策:规则性同业矩阵填 `target_slots`,复杂跨资产公式填 `target_formulas`,标签替换填 `page_label_replacements`。`decisions` 已按角色预生成嵌套占位骨架(`{"roles":{"":{...}}}`),只需要在骨架里补全空值,不要新增/改写顶层字段,也不要把 `required_decisions` 里的扁平 `decision_id`(如 `roles.package.package_001.target_formulas`)当成提交用的 key。禁止直接编辑标准 fork HTML/review。 - Grant按来源角色完整继承 `kind/query_type/fields/dimensions/window_days/result_mode` 与 CSV/inline 合同,只允许自动修改 manifest 声明的资产范围字段;其他变化必须填写 `contract_change_reason`。 - 继承 Grant 的数据级失败可降级并继续发布存活角色;鉴权/配额/协议等系统级失败仍阻断。若页面仍用 `queryDataGrant` 无条件消费失败 Grant,返回 `GRANT_DEGRADATION_UNSAFE`,不得用空凭证假降级。 - 先运行 `fork_prepare` 返回的 `review_update_command`;只有 `review_state.status=complete` 且生成 review receipt 后,才运行 `publish_command`。发布器从同一 canonical package/Grant 合同派生 QBS 验证与注册,自动检查 required outputs、公式左值、reads、PE/PB 水位公式具有明确算法与正整数窗口、Grant fingerprint、Marker 唯一性与 Card Runtime 结构,并让一次注册结果扇出到页面/Card全部位置。 - `fork_manifest_v2` 禁止手工传 packages、grants、Marker 或完整 workflow JSON,出现 `MANUAL_RUNTIME_BINDINGS_FORBIDDEN` 时回到生成的 publish plan,不要写临时替换脚本。v1 prepared task 继续按旧接口发布。 - 这不是建议——`publish_verified` 服务端会按 fork manifest 里的凭证数量强制核验:手工分步调用 `publish_verified(task_id, page_id, html_file, source_template_id, fork_manifest_file, validation_receipt_files)` 只有在这个页面**零凭证**(纯静态改造)时才会放行,否则直接拒绝并返回 `error:"PUBLISH_WORKFLOW_REQUIRED"`;出现该错误时改走 `publish_workflow.py`,不要绕过。 - 回复 = 回复模板格式 + **自己的新链接**(数值同样用自己的包/grant query 填)。 - **③ 未命中**(无匹配范式):Agent 根据 `items_summary` 调 `new_page` 时传 `routing_decision:{"mode":"unmatched","closest_template_id":"page_xxx","reason_code":"required_capability_missing","reason":"候选缺少用户要求的核心能力"}`;存在候选却只因标的/范围不同而判 unmatched 会被提示改走 fork。记录成功后继续 `build_dashboard` / bespoke 自建 → 其余同 ②;`feishu-group` 同样不发送进度链接。 > 后续追问:自己的链接 → `update` 同 `page_id`;命中的官方/社区链接要改 → 只能转 ② fork 成自己的链接后再改。 ## 默认路由 - **简单单一 A 股综合分析**(无定制、额外指标/图表、对比或多标的要求):`trace_context begin` 后先 QBS 完整业务首答,再 `new_asset_page(reply_mode:"page_followup")`,验收后补链接;宿主不能中途显示首答时用默认完整终态回复。 - **其他固定页面形态**(定制个股页、成分股异动榜、多因子选股看板、商品日报等):先 `templates` 查询官方精选+社区命中池;direct 直接用列表 URL + revision,fork 才读取和改写模板详情。 - **宽宝活卡 / 精华卡 / 封面卡(范式卡 artifact)**:把页面精华做成独立 **card runtime artifact**(`embedded-card-v1`:页面内嵌 `