Skip to content

fix: recover oversized briefings through files / 超大 briefing 文件恢复 - #165

Open
harr1sz wants to merge 1 commit into
titanwings:distilly-pluginfrom
harr1sz:codex/fix-file-briefing-recovery
Open

harr1sz wants to merge 1 commit into
titanwings:distilly-pluginfrom
harr1sz:codex/fix-file-briefing-recovery

Conversation

@harr1sz

@harr1sz harr1sz commented Sep 13, 2026

Copy link
Copy Markdown

English

Problem and approach

Addresses #149. Research can be successfully ingested but then exceed a host's verified MCP briefing limit. Increasing the model context setting does not change that transport limit, and telling the user to reduce the next batch does not recover the material already waiting.

Add an explicit local command:

distilly recover <job-id> --output <new-directory> [--timeout-seconds 1..1500]

The command opens the existing Preview LocalRuntime with an explicit SDK file budget. It exports the complete briefing, the existing commit schema, and instructions to a new private directory. The user or agent reads the briefing and writes a response containing its SHA-256 and a DistillPatch. The command submits that patch through the same session and lease, with identity fields taken from the original briefing. Existing schema, evidence, generation, and lease checks still decide whether the commit is accepted.

This keeps the five-tool MCP contract and verified host fixtures unchanged. It adds no dependency, database migration, or model call. It does not truncate research, split the task, delete materials, or generate an empty patch.

Failure and recovery behavior

  • Atomically reserve a new directory with mode 0700; write command-owned files exclusively with mode 0600. Existing paths are preserved, and recovery artifacts are never automatically removed.
  • Read only a bounded regular response file. Reject symlinks, oversized or incomplete JSON, mismatched briefing digests, and extra commit identity fields. Documentation requires writing a temporary file and renaming it when complete.
  • Wait 20 minutes by default, with a 25-minute maximum below the 30-minute lease lifetime. Timeout, cancellation, and rejected responses attempt to release only this session's lease. Another owner's live lease remains untouched. A force-killed process must wait for lease expiry.
  • Persist the submission and request ID before committing. Distinguish a successful commit whose receipt could not be written from an unknown internal commit outcome, and tell the user to inspect the result before retrying. Suspended results retain the normal review workflow.

The file workflow supports complete briefings within the existing 4 MiB / 999-reference engine limits. Its file budget is not evidence of a larger MCP or model context capacity. Response files are limited to 256 KiB, while the existing 64 KiB canonical patch limit remains in force. Larger engine-level workloads still fail explicitly.

INSTALL.md contains English and Chinese instructions. The architecture note, canonical design chapter, generated chapter, and capacity error remediation point to this workflow.

Validation

Node 22.22.1, pnpm 10.32.1, Python 3.9.6:

  • Added 19 regression cases covering a source rejected at 64 KiB, exact-evidence commit, digest mismatch, invalid evidence, file boundaries, timeout, cancellation, CLI signal-handler cleanup, existing lease ownership, refusal to overwrite artifacts, and receipt failure after a durable commit.
  • Full pnpm run test ran all 1,016 Vitest tests: 1,014 passed and two unchanged engine tests exceeded their default 5-second timeout. Both files and the new recovery tests passed in a separate single-worker run: 56 tests, with the original timeout unchanged. The full command is therefore not reported as a clean single-run pass.
  • Build, typecheck, formatting/lint, documentation verification, and git diff --check passed. Panel browser, 49 package-boundary tests, 34 build-artifact tests, and 13 Python Plugin tests also passed when run separately after the full pipeline stopped at Vitest.
  • A separate smoke test launched the built CLI as a child process against the same store as a live observer. It exported a complete 98,532-byte briefing containing a 91,030-byte source, rejected the observer's competing lease request, committed a current version, and left zero pending jobs. The CLI exited with code 0.
  • Independent source review found no remaining blocking issue. This is local runtime/file transport validation; real-host/model acceptance and full release coverage/hygiene gates were not run.

This PR is independent of correction membership fix #164 and targets distilly-plugin.

中文

问题与方案

对应 #149:调研资料可以成功入库,却因 briefing 超出宿主已验证的 MCP 上限而无法继续。增大模型上下文不会改变这个传输限制;建议用户缩小下一批资料,也无法处理已经入库的任务。

新增显式命令 distilly recover <job-id> --output <new-directory> [--timeout-seconds 1..1500]。命令使用现有 Preview LocalRuntime 和明确的 SDK 文件预算,将完整 briefing、原有 commit schema 和操作说明导出到新建的私人目录。用户或 Agent 阅读资料后,写入包含 briefing SHA-256 和 DistillPatch 的响应;命令再通过同一会话和租约提交,提交身份字段全部取自原始 briefing。是否接受结果,仍由原有 schema、证据、generation 和 lease 校验决定。

五工具 MCP 契约和已验证宿主的容量 fixture 不变;不增加依赖、数据库迁移或模型调用,也不裁剪资料、拆分任务、删除材料或自动生成空 patch。

失败与恢复

  • 原子创建权限为 0700 的新目录,以独占方式写入权限为 0600 的文件。保留已有路径,不自动删除恢复产物。
  • 只读取大小受限的普通响应文件。拒绝符号链接、超大或不完整 JSON、摘要不匹配,以及额外提交身份字段。文档要求先写临时文件,完成后再重命名。
  • 默认等待 20 分钟,最多 25 分钟,低于租约的 30 分钟有效期。超时、取消或响应被拒绝时,只尝试释放本会话租约,不接管其他会话的有效租约。进程被强制杀死时需等待租约过期。
  • 提交前保存输入和请求 ID。区分“提交成功但回执写入失败”与“内部异常导致提交结果未知”,提示先查询结果再重试。suspended 结果仍需正常审核。

文件恢复仍受引擎原有的 4 MiB briefing 和 999 个资料引用上限约束。文件预算不能证明 MCP 或模型上下文容量已提高。响应文件最多 256 KiB,canonical patch 的 64 KiB 上限保持不变;超过引擎上限的任务仍明确失败。

INSTALL.md 提供中英文操作说明;架构说明、设计源文档及生成章节、容量错误提示均已同步。

验证

环境:Node 22.22.1、pnpm 10.32.1、Python 3.9.6。

  • 新增 19 个回归场景,覆盖被 64 KiB 上限拒绝后的恢复、精确证据提交、摘要与证据错误、文件边界、超时、取消、CLI 信号监听清理、已有租约、不覆盖原文件,以及提交成功后的回执写入失败。
  • 完整 pnpm run test 执行了 1,016 个 Vitest 测试:1,014 个通过,两个未修改的引擎测试超过默认 5 秒时限;随后单 worker 重跑这两个文件和新增恢复测试,56 个测试全部通过,未放宽原超时设置。因此不把首次全量命令报告为一次性全绿。
  • 构建、类型检查、格式与 lint、文档校验、git diff --check 通过。全量流程在 Vitest 处停止后,另行执行的 Panel 浏览器检查、49 个包边界测试、34 个构建产物测试和 13 个 Python Plugin 测试均通过。
  • 独立 smoke 启动构建后的 CLI 子进程,并保留一个访问同一存储的观察进程。完整导出包含 91,030 字节源资料的 98,532 字节 briefing,观察进程抢占租约被拒绝,最终提交为 current,待处理任务为零,CLI 退出码为 0。
  • 独立源码审查未发现剩余阻塞问题。这里验证的是本地运行时与文件恢复流程,未运行真实宿主/模型验收或完整发布 coverage/hygiene gates。

此 PR 与修正资料归属的 #164 相互独立,目标分支为 distilly-plugin

Export a complete briefing through an explicit local CLI session, bind its
response to the exported digest, and commit using the original lease.
Preserve evidence validation and host capacity fixtures. Add bounded private
file handling, cancellation, lease cleanup, truthful commit receipts, and
19 regression cases. Document the workflow and its limits in English and Chinese.

通过显式本地命令导出完整 briefing,以摘要绑定响应,并沿用原租约提交。
保留证据校验和宿主容量 fixture,补充受限的私人文件读写、取消与租约
清理,以及提交回执的准确状态提示。新增 19 个回归场景,并用中英文
说明操作流程和容量限制。

Addresses titanwings#149.
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