Replies: 4 comments 1 reply
EN / EnglishEvidence chain — every rejection site (verbatim, @rc.2)F1 — dsh-session/lib/types/index.js:30-31 (the session header check) if (record.version !== SESSION_FORMAT_VERSION) {
throw new Error(`session header version must be ${SESSION_FORMAT_VERSION}, got ${String(record.version)}`);
}
F2 — dsh-session-persistence/lib/index.js:1103-1106 ( assertVersion(meta) {
if (meta.version === SESSION_FORMAT_VERSION) return;
throw this.unsupported(meta, sessionFormatVersionRefusal(meta.id, meta.version));
}F3 — dsh-session-persistence/lib/index.js:481-483 (the refusal text itself) function sessionFormatVersionRefusal(id, version) {
return version > SESSION_FORMAT_VERSION
? `... the log was written by a newer harness — upgrade the harness to open it`
: `... older than the supported v${SESSION_FORMAT_VERSION}, and this build ships no upgrade path for it`;
}The F4 — dsh-session-persistence-jsonl/lib/index.js:181-195 ( function refuseForeignFormatVersion(parsed) {
if (typeof parsed !== "object" || parsed === null) return;
const { version, id } = parsed;
if (typeof version !== "number" || version === SESSION_FORMAT_VERSION) return; // :184
throw new SessionFormatUnsupportedError(sessionFormatVersionRefusal(...)); // :185
}Plus encoding-mismatch hard refusal at F5 — dsh-subagent/lib/index.js:328 (const) + :386 (check) const SUBAGENT_DESCRIPTOR_VERSION = 2; // :328
...
if (version !== 2) return void 0; // :386 — silently skips, does NOT upgradeF6 — dsh-llm-deepseek/lib/index.js:522 if (index.formatVersion !== 3 || !Array.isArray(index.records)) throw new InvalidUploadIndexError("llm-deepseek: unsupported upload index format");F7 — dsh-llm-pi-ai/lib/index.js:100 if (response["version"] !== 2) return invalidReplay(`unsupported version ${String(response["version"])}`);Why a bump = mass unreadable (mechanics)The refusals are gated only on
The asymmetry that makes it dangerousF3's message implies "upgrade the harness and it'll open" — but upgrading changes the current version, which only makes the reader expect the new format. Old v0 logs still don't match → still 中文版 / ZH证据链 —— 每一处拒绝点(原文,@rc.2)F1 — dsh-session/lib/types/index.js:30-31(会话头校验) if (record.version !== SESSION_FORMAT_VERSION) {
throw new Error(`session header version must be ${SESSION_FORMAT_VERSION}, got ${String(record.version)}`);
}
F2 — dsh-session-persistence/lib/index.js:1103-1106( assertVersion(meta) {
if (meta.version === SESSION_FORMAT_VERSION) return;
throw this.unsupported(meta, sessionFormatVersionRefusal(meta.id, meta.version));
}F3 — dsh-session-persistence/lib/index.js:481-483(拒绝文案本身) function sessionFormatVersionRefusal(id, version) {
return version > SESSION_FORMAT_VERSION
? `... the log was written by a newer harness — upgrade the harness to open it`
: `... older than the supported v${SESSION_FORMAT_VERSION}, and this build ships no upgrade path for it`;
}
F4 — dsh-session-persistence-jsonl/lib/index.js:181-195( function refuseForeignFormatVersion(parsed) {
if (typeof parsed !== "object" || parsed === null) return;
const { version, id } = parsed;
if (typeof version !== "number" || version === SESSION_FORMAT_VERSION) return; // :184
throw new SessionFormatUnsupportedError(sessionFormatVersionRefusal(...)); // :185
}外加编码不匹配硬拒: F5 — dsh-subagent/lib/index.js:328(常量)+ :386(校验) const SUBAGENT_DESCRIPTOR_VERSION = 2; // :328
...
if (version !== 2) return void 0; // :386 —— 静默跳过,不升级F6 — dsh-llm-deepseek/lib/index.js:522 if (index.formatVersion !== 3 || !Array.isArray(index.records)) throw new InvalidUploadIndexError("llm-deepseek: unsupported upload index format");F7 — dsh-llm-pi-ai/lib/index.js:100 if (response["version"] !== 2) return invalidReplay(`unsupported version ${String(response["version"])}`);为什么 bump = 全部不可读(机制)拒绝逻辑只按
让它危险的不对称F3 的文案暗示"升级 harness 就能打开"——可升级只是把当前版本改掉,reader 只会期待新格式。旧的 v0 日志依然不匹配 → 依然 |
|
For this persistence-format failure, the handbook's Session storage guide recommends recording the exact package/source revision, schema/version markers, and whether the reader is cold restore or live replay before attempting edits. It also keeps migration and rollback separate from deleting logs: https://github.com/sandbaseai/deepseek-harness-handbook/blob/main/docs/en/reference/session-log-storage-format.md |
|
Follow-up: the Session storage-format guide now captures the format-evolution gap from this report. It distinguishes unsupported versions from corruption and defines evidence-preserving migration/rollback gates in v0.5.291: https://github.com/sandbaseai/deepseek-harness-handbook/releases/tag/v0.5.291 |
EN / EnglishFix directions (directions only — not a patch)
Suggested priority
How this gap sits with the other architecture gapsThis is the format-evolution dimension of the same root pattern we've been mapping: DSH is self-consistent in an ideal static environment, but lacks basic contracts for a must-evolve production environment. It joins three sibling gaps already documented in our audit:
Format v0 with no migration is the fourth: correctness is assumed to never require a format change — but production inevitably does. Any one necessary fix turns "the data is safe" into "all history is gone", with no rollback. 中文版 / ZH修复方向(仅方向,非补丁)
建议优先级
本缺口如何与其余架构缺口并列这是我们一直在梳理的同一根因模式的格式演进维度:DSH 在理想静态环境下自洽,却缺乏必须演进的生产环境所需的基础契约。它与我们审计中已记录的三处缺口并列:
格式 v0 无迁移 是第四处:正确性被假设为"永远不需要改格式"——但生产必然要改。任何一次必要的修复,都会把"数据很安全"变成"全部历史没了",且无回退。 |
Uh oh!
There was an error while loading. Please reload this page.
EN / English
TL;DR
Every durable format in DSH stamps a
versionand hard-refuses any non-current version, yet nowhere in the codebase is there a migration, upgrade, or dual-write path. TodaySESSION_FORMAT_VERSION=0(and descriptor v2 / upload-index v3 / replay v2) all happen to be the first version, so the refusals never fire. The moment a format must change — and production-grade use inevitably forces it — every already-on-disk session becomes unreadable at once, with no rollback. This is not a rendering bug; it is a format-evolution contract gap at the persistence layer.What every persistence layer does today
SESSION_FORMAT_VERSION(=0)record.version !== SESSION_FORMAT_VERSION→ throwassertVersion→ throwunsupported:482)refuseForeignFormatVersion→ throwSessionFormatUnsupportedError; encoding mismatch also throwsSUBAGENT_DESCRIPTOR_VERSION=2version !== 2→return void 0(skip, no upgrade)formatVersion=3index.formatVersion !== 3→ throwInvalidUploadIndexErrorversion=2response["version"] !== 2→invalidReplayThe README is explicit (dsh-session-persistence-jsonl/README.md:38): "There is no migration, mixed-root fallback, or dual write." And :72: "Only the configured encoding and current
SESSION_FORMAT_VERSION(v0) load … the pre-release format has no migration."Why this is a production time-bomb, not a "pre-release quirk"
The current silence is purely because the version has never been bumped. That is a pre-release lock-state, not a designed evolution strategy. But production-grade operation forces a bump:
When any bump ships, F1–F4 immediately
throwon every existing v0 log. The F3 message tells users to "upgrade the harness" — but upgrading still offers no upgrade path; old logs stay unreadable. There is no migration window, no dual-write, no rollback.Blast radius
What's in the follow-ups
中文版 / ZH
一句话
DSH 每一层持久化格式都戳了
version并硬拒任何非当前版本,但整个代码库里没有任何迁移 / 升级 / 双写路径。今天SESSION_FORMAT_VERSION=0(以及 descriptor v2 / upload-index v3 / replay v2)恰好都还是首发版本,所以拒绝逻辑从未触发。可一旦格式必须变更——而生产级使用必然逼出变更——所有已落盘的会话会瞬间全部不可读,且无回退。这不是渲染 bug,是持久化层的格式演进契约缺口。今天每一层持久化在做什么
SESSION_FORMAT_VERSION(=0)record.version !== SESSION_FORMAT_VERSION→ throwassertVersion→ throwunsupportedrefuseForeignFormatVersion→ throwSessionFormatUnsupportedError;编码不匹配同样 throwSUBAGENT_DESCRIPTOR_VERSION=2version !== 2→return void 0(跳过,不升级)formatVersion=3index.formatVersion !== 3→ throwInvalidUploadIndexErrorversion=2response["version"] !== 2→invalidReplayREADME 说得很直白(dsh-session-persistence-jsonl/README.md:38):"There is no migration, mixed-root fallback, or dual write.";:72:"Only the configured encoding and current
SESSION_FORMAT_VERSION(v0) load … the pre-release format has no migration."为什么是生产级定时炸弹,而非"pre-release 小瑕疵"
现在的风平浪静,纯粹是因为版本号从未 bump 过——这是 pre-release 的锁版本状态,不是设计好的演进策略。但生产级运营必然逼出 bump:
任一 bump 上线后,F1–F4 会立刻对所有现存 v0 日志
throw。F3 的文案让用户去*"upgrade the harness"*——可升级后仍然没有 upgrade path,旧日志还是读不了。没有迁移窗口、没有双写、没有回退。爆炸半径
跟帖说明
署名 / About this report
EN: Reported by the OfferKuai (Offer快) Team — an AI startup building full-lifecycle job-application services, guided by the belief that "users need results, not repeated conversations." Founder: Zhaofeng (Yaming). We use DeepSeek Harness as part of our daily development workflow; this report is our way of contributing back to the ecosystem. Website: https://www.offerkuai.com/ | Contact: contact@offerkuai.com
ZH: 本报告由 OfferKuai(Offer快)团队提交 —— 一家专注 AI 全流程求职托管的创业团队,核心理念是「用户要的是结果,不是重复对话」。创始人:Zhaofeng(Yaming)。我们将 DeepSeek Harness 用于日常开发工作流,这份报告是我们对社区的回馈。官网:https://www.offerkuai.com/ | 联系:contact@offerkuai.com
All reactions