# Jev 单流程筛选：当前契约（N_off, schema v5）

本文是 `adaptive_search` 生产契约的当前说明，对应 N_off 单流程：一次有界 fused 候选快照 + 一次固定选项 Jev 策略请求 + 一次固定选项筛选。它取代此前的 v3 关键词循环说明；历史文档（`adaptive-keyword-index.md`、`adaptive-history-aware-audit.md`、`adaptive-review-points.md`、`adaptive-fused-screening-plan.md`）只对应旧版本或原型设计，其中被本流程替代的部分不再生效。

- 数值公式与价值等级沿用 screening 原型（`fused-screening-mix-v2-prototype`），本文不重复公式推导，见 `docs/adaptive-fused-screening-plan.md` 与 `lib/search/screening/scoring.js`。
- 预算语义以 2026-10-02 的补充修正为准：**没有任何自设的累计成本、token、请求次数或整次调用时限可以停止本流程**；用量只做观测与披露。

## 1. 输入契约与旧字段迁移

正常新研究：

| 字段 | 契约 |
| --- | --- |
| `questions` | 恰好一个非空字符串，最长 400 字符。就是唯一检索 query，不做关键词规划或查询扩展。 |
| `intent` | **必填**非空字符串，最长 2000 字符；不再由问题自动填补。 |
| `preferences` | 可选 0-8 条非空软偏好，每条最长 300 字符；按键精确去重后等权平均，只加分。 |
| `community` | 可选严格 boolean，无 schema 默认值。省略 = 由同一次策略请求选择 `enable`/`disable`/`unknown`；显式 true/false 覆盖且不再提问该题。 |
| `save_results` | 可选严格 boolean，默认 false。true 时私有保存**完整的最终选中集**与类型化元数据。 |
| `max_results` | 保存/交付的目标条数，默认 10，范围 1-50。 |
| `page_size` | 每页条数，默认 20，范围 1-50；不改变排序、selection、totalResults 或 targetMet。 |

只读输入：`cursor`（`s5:` 本次运行页 / `h1:` 历史只读页）或 `saved_result_id`（36 位小写 UUID），只可搭配 `page_size`。

迁移规则：

- `constraints` 作为逐材料硬门槛已退役。省略或传 `[]`（返回 `deprecated_constraints_empty` 警告）；非空合法数组在任何检索/Jev 调用前以 `adaptive_constraints_removed` 拒绝；类型/长度/元素无效按输入错误拒绝。
- `keywords`、`tasks`、`targets`、`facts`、`time_range`、嵌套关键词数组等旧字段一律零网络拒绝，不做静默丢弃。
- `cursor` / `saved_result_id` 不得与任何新研究字段（包括 `save_results:false`、`community:false`、`constraints:[]`）混用，两个读取 ID 也不能并用。
- 结构与旧字段检查在配置读取、工具状态检查与所有网络之前完成。工具描述继续提示 questions 与 intent 必须使用英文，但这是调用方提示，不做语言校验、拒绝、翻译或诊断；任何语言都按原文检索。

## 2. 唯一执行流程

```
结构与迁移校验（零网络）
→ 公开入口门控（显式 OFF / Jev 配置锁）+ 外部 signal
→ cursor / saved_result_id 只读分支在此结束（不建 Jev 客户端、不问策略、不检索、不判断）
→ 一次固定策略请求：选 ranking；community 省略时同一次选 enable/disable/unknown
→ 代码解析显式覆盖 / 模型选择 / unknown 与缺失回退，落实能力与域名限制
→ 调用共享 runFused：query=原问题，medium，candidateSelection=snapshot，community=解析后的布尔值
→ 有界快照（目标 ≤10 时最多 32 条；更大目标为 ceil(max_results × 32 / 10)，最高 160；网页与社区行共用）按原融合分与稳定 key 全局排序后截取
→ prepareMaterial 校验/哈希并标记 pending → 分批固定选项 safety/value/source discount/preferences
→ 代码排除安全失败、基础分无效、不可判断、value 未建立与 value<3
→ 原型 screeningScore + 稳定 tie-break + max_results 截断 → schema v5 结果
→ save_results:true 时保存完整最终选中集，然后建立进程内 s5: 分页
```

没有第二轮检索、没有关键词续搜、没有自动补读（`rescueReads` 固定为 0）、没有 N_on/N_off 开关、没有第二个 adaptive 入口。

## 3. 搜索前策略与 community 优先级

- 策略请求只含 `strategy.ranking` 与（省略 community 时）`strategy.community`；criteria 由代码提供，Jev 只返回选项，不产生平台名、引擎、查询变体、预算或系数。
- 优先级：显式 boolean（按字段是否存在识别，不被 truthy/默认值覆盖） > 模型选择 > 缺失/非法回退。`enable→true`、`disable→false`、`unknown→false`；缺失/坏形状/非法 option 同样 false，但状态记为 unavailable 并披露，不伪装成模型选择 disable。
- 能力处理基于同一个 runtime capability snapshot：官方 X 不可用但既有 fallback 可用时按原机制执行；已知整条支路不可执行或被授权边界禁止时跳过并返回结构化 `unavailable`/`blocked`；普通路由无可用引擎时仍 `no_engines` 失败。
- `run.community` 输出固定结构：`input`、`source`、`choice`、`requested`、`effective`、`outcome`、`cacheHit`、`reason`、`usage`；状态只来自共享核心的结构化执行记录，不解析 warnings 文案，也不从 `communityUsed` 推断成功。
- 公开 `x_search` 入口开关只关闭公开入口，不是内部引擎授权表；searcher 对 fused_search/fetch_page 的依赖检查也不适用于本流程。
- 当前内置 snapshot 没有独立的 X 禁用/宿主权限配置，`fallback.available` 表示既有无需凭据入口可尝试，不是联网成功保证。`blocked` 仅在宿主明确提供 `capability.x.blocked` 时产生，不会把公开工具 OFF 当作内部禁令；配置不足、实际失败与无引擎分别按真实路径披露，不能仅凭官方不可用关闭 fallback。
- `run.community.usage` 保留有限的 `officialAttempted` / `fallbackAttempted` / `dispatchedNow` / `inFlight` 布尔标记及计数。HTTP/账单 token 未观察到时为 null；共享缓存或 in-flight 复用的本次派发/请求计数为 0，原 `partial` 等执行状态仍保留，不重复计费式计数。

## 4. 判断、价值与来源

- safety 固定选项 `clear`/`violation`/`unavailable`，与语义相关性独立，missing 不作为 clear；结构有效只是 pending。
- value 固定 0-5 与 `unestablished`；只交付已建立且 ≥3 的等级，低价值、未建立与服务不可用分开披露。`qualityAssessed` 是原型口径：通过准入并获得 value≥3 的候选数，不等于拿到 value 答案的候选数。beta.6 新增 `diagnostics.valueJudged`，单独统计得到有效 value 等级或显式 unestablished 答案的候选（包括低价值和安全拒绝行），不可用答案不算；它与准入数不能混用。
- 来源折扣只对真实正贡献引擎的固定选项生效；缺失来源中性且披露；confidence 只做审计，不参与评分、阈值或准入。
- 偏好精确去重后取平均；反例可以有高 value 或匹配偏好；`valueGroups` 是最终结果标签索引，不改变排序。默认仅 URL 去重、`mu=0`、`dedupe=false`。

## 5. 资源边界与用量观测

容量/协议上限（不是累计预算）：`candidateLimit=max(32, ceil(max_results × 32 / 10))`（公开目标最高 50，对应容量最高 160）、`batchSize=4`、每次最多 1 次重试、Jev 响应最大 24000 字节、state/request 上限 48000/60000 字符、初始材料最多 8000 字符、单请求 20 秒、回退最多 4 秒、`rescueReads=0`。

beta.6 保留原先默认目标 10 / 容量 32 的筛选余量比例；12 条目标对应 39，50 条目标对应 160。该容量在一次检索前确定，并贯穿 engine 请求、共享快照截取、缓存键及 `run.limits.candidateLimit`。内部显式容量覆盖仍有权威性并校验整数 1–500；覆盖小于目标时仍披露 `targetExceedsReviewCap`。不追加检索，不因已够数量提前停止，也不保证上游能供足或筛选后必然足量。扩大目标会增加判断量；标准四条批次下，160 个实到候选需约 1 次策略 + 40 批 Jev 判断（长文本尺寸拆批、重试另计），默认 10 条目标仍为原容量。

网页与 X/community 共用全局快照上限，不表示两条支路各自都能供满该容量：既有 X 支路最多返回 30 个候选，beta.6 扩大全局容量不改变它。若 160 条容量被填满，其余至少 130 条须来自网页；实际供应和筛选后数量仍不保证。

用量计量（`screening-metering-v3-no-cumulative-cap`）只记录发生过的调用与估算，并在 `usage` 中披露：`fusedCalls`、`engineRequests`（null=未知）、`jevCalls`、`jevHttpAttempts`、`jevRetries`、`jevInputTokensEstimated`、`jevTokensEstimatedReserved`、`jevInputTokens`/`jevOutputTokens`（未上报即 null）、`serverUsageCalls`、`unknownUsageCalls`，以及本层 `fetch*` 的真实 0。达到任何旧上限都不会拒绝后续请求，也不会中止已有效结果。

真实单请求超时、有限重试、认证/限流/网络错误、SSRF/重定向与内容安全、显式取消继续生效；取消后不派发新请求，批次失败保留已有效材料。MCP/DSH 的 `adaptive_search`、`fused_search`、`x_search` 均不设置整次搜索总时限；SDK/宿主/提供商自身的外部硬限制仍可能存在，不能将它们描述为无限运行。`fetch_page` 的读取保护及研究子任务显式时限不因本补充取消。

## 6. 返回、分页与持久化

- 所有新研究直接 `schemaVersion=5`，策略版本：`fused-screening-mix-v2-prototype`、`screening-judgement-v4-no-scope-no-language`、`screening-strategy-v2-community-no-language`、`no-scope-v1`、计量 `screening-metering-v3-no-cumulative-cap`。
- 结果行含 ID/rank、URL/标题/准确摘录、basis/日期/文本与分数版本、真实来源、`valueLevel`/`valueLabel`、分数组件、来源折扣与偏好匹配、有意义的 value/discount confidence。
- `selection` 给出 `requested`/`returned`/`targetMet`/`stopReason`/`incomplete`；`diagnostics` 给出计数守恒与排除原因；`outsideReview`/`unreviewed` 统计尚未进入判断或快照之外的候选；已派发但判断不可用的候选另计入 `judgementUnavailable` / `assessmentUnavailable` / `safetyUnavailable`，因此 `unreviewed=0` 不代表全部判断有效。失败或取消批次的 `judgeFailures` 是派发失败计数，原因结合 `stopReason` 查看；不可用判断绝不当作低价值或不存在。`targetMet` 只表示数量。
- 新响应不返回 `keywordProgress`、`retrievalSufficient`、`coverageComplete`、`scopeSummary`、`convergence`、`finalReview`、`tier`/`valueScore` 等旧字段，也不填假零/假 true。
- 页面软容量为 96,000 UTF-8 字节（原先 45,000），元数据仍保留 16,000 字节预算；按三条 8,000 字符中文摘录（约 72,000 字节）及字段开销协调容量，避免常规长中文结果被迫每页一条。page_size 仍是条数上限，不保证装满；超软限单条仍完整交付并告警，绝不截改已审摘录。读取/完整保存集合的语义不变。合法长中文或 JSON 转义输入若使元数据超限，页面仅缩短 `inputSummary` 的 Unicode 完整前缀并告警；真实检索/判断输入、已审摘录、计数与使用量不变，显式保存成功时私有快照保留完整输入。历史 v1 元数据仍原样返回，不套用此缩短。
- 分页：进程内共享 30 分钟 / 32 份页面池，`s5:` 对应 v5 运行、`h1:` 对应历史只读恢复；拒绝裸 UUID.offset、`s4:`、过期/驱逐/越界 cursor，且零网络。`clearAllCaches` 只清内存/检索缓存，不删除持久快照。
- 持久化：新写入 `search-boost-research-v2` + `metadata.schemaVersion=5`；读取按 `format` 分派，v2 校验失败绝不降级 v1。旧 v1 文件只读恢复，返回 `restoration={historical:true, originalFormat, originalSchemaVersion}` 与 `h1:` cursor，保留原结果与元数据、不伪造 v5 字段、不就地升级、不刷新 `savedAt`。存储保留 64MiB 上限、UUID 文件名单硬链接与 NOFOLLOW 校验、0700/0600 私有原子写入、递归白名单清洗、取消不返回成功 ID、CLI 离线 `research list`/`research export` 与 `wx` 不覆盖。

## 7. 失败语义

真实结构错误、认证、网络、无引擎、安全拒绝、取消、超时按真实原因返回；社区支路失败或部分失败时仍交付已筛选的网页结果并把 `selection.incomplete=true`、`stopReason=community_incomplete`（除非已有更具体的停止原因）。空结果不证明不存在；被拒绝的旧 constraints 内容不发送给 Jev。成功读取一份原本 `stopReason=not_configured`/失败/空结果的历史文件表示本次读取成功，不触发新的配置诊断。

## 8. 验证边界

仓库内的离线 fixture 只证明机制、契约与失败语义，不证明线上策略质量、语义准确率或研究完成度。发布前按 `docs/test-isolation.md` 运行隔离门禁；`scripts/test-adaptive-capacity.mjs`、`scripts/test-screening*.mjs`、`scripts/test-adaptive-search.mjs`、`scripts/test-screening-hosts.mjs`、`scripts/test-fused-baseline.mjs`、`scripts/test-noff-community-snapshot.mjs` 与 `scripts/test-research-persistence.mjs` 是本文契约的自动化证据。迁移说明与退役清单见 `docs/adaptive-screening-migration.md`。
