Skip to content

fix: load crash on dsh 0.1.2-alpha.5+ (settings schema), session replay lineage, and snapshot walk hardening (.gitignore, budgets, abort) - #25

Open
IMJoyJ wants to merge 4 commits into
PerryLink:mainfrom
IMJoyJ:fix/copy-gitignore-and-budget
Open

IMJoyJ wants to merge 4 commits into
PerryLink:mainfrom
IMJoyJ:fix/copy-gitignore-and-budget

Conversation

@IMJoyJ

@IMJoyJ IMJoyJ commented Sep 14, 2026

Copy link
Copy Markdown

Summary

Three fix areas, each with tests (278 unit + integration green on Windows; CI covers Windows/Linux × Node 22/24):

  1. Settings schema: zod → Schemastery (load crash). Host settings.register (dsh 0.1.2-alpha.5 and later) invokes the namespace schema as a function; a zod instance is not callable, so the plugin fails to load with TypeError: schema is not a function. Ported to Schemastery (enums via z.union, defaults kept identical), with numeric/non-empty boundary checks moved into validateCheckpointSettings so validation strength is preserved.

  2. Session replay on 0.1.2-alpha.5+. Session.events getter removed in favor of snapshotEvents(); header seedLength split into isSeeded + inheritedEventCount. replaySession now uses ctx.sessions.fork() when the host provides it (same boundary semantics as the local replaySeedOf, plus open-turn validation), otherwise falls back to generation-appropriate create() options. Fork lineage is preserved instead of silently dropped.

  3. Snapshot walk hardening (.gitignore + budgets + abort). The copy provider walked the whole workspace ignoring the project's own ignore intent — an intended-huge .gitignored tree (a deck-cache folder with ~871k files) made a single snapshot take hours and stall the guarded tool call indefinitely.

    • Honors .gitignore (root + nested, deeper rules and ! re-includes win, via the ignore package) evaluated before stat, so ignored subtrees cost nothing. New respectGitignore config (default true).
    • Budget guardrails: maxSnapshotFiles (default 100k) and snapshotTimeoutMs (default 180s) skip an oversized walk with a loud warning (SNAPSHOT_BUDGET_EXCEEDED) instead of stalling — a snapshot is a safety net and must never cost more than the operation it protects. maxSnapshotBytes keeps its pruning soft-quota semantics (not a walk abort).
    • Cancellable captures: per-session AbortController fired on turn/end (cancelled/interrupted) and agent/disposed (SNAPSHOT_ABORTED) — agent.cancel can now break an in-flight walk.

Test plan

  • npm test: 278 pass / 0 fail (includes 12 new provider cases: gitignore root/nested/negation/toggle, files+timeout budgets, within-budget no-op, signal abort; 2 new settings-boundary cases).
  • npm run test:integration: ALL PASS ×3 consecutive runs (copy flow, git flow, v1 medium flow).
  • Five-language README table + intro synced; CHANGELOG (Unreleased) and ARCHITECTURE decision records D18/D19 added.

🤖 Generated with agent assistance

JoyJ added 3 commits September 27, 2026 16:57
- copy provider 读取工作区 .gitignore(根+嵌套,深层与 ! 取反胜出,
  lib/ignore-files.mjs 用 ignore 标准库),在 stat 之前剪掉被忽略子树——
  有意庞大的 ignore 目录(卡组缓存/构建产物)不再让整树快照花上数小时
  (真实事故:87 万 .gitignore'd 文件被全量拷贝,变更步骤卡死 12h+)。
  Config.respectGitignore 默认开;#listLeftovers 用同一组合排除器。
- 遍历预算护栏:maxSnapshotFiles(默认 100000)与 snapshotTimeoutMs
  (默认 180000)超限时以 SNAPSHOT_BUDGET_EXCEEDED 跳过本次快照并响亮
  告警(含修复提示),被保护的工具调用必定继续——快照是安全网,绝不能
  比被保护的操作更贵。maxSnapshotBytes 维持清理软配额语义,不作遍历中止。
- 在飞捕获可取消:每会话注册 AbortController,turn/end(cancelled/
  interrupted)与 agent/disposed 触发中止(SNAPSHOT_ABORTED)——
  agent.cancel 终于能解脱在飞瀑布;预算/中止错误跳过去重基线重试。
- 新增依赖 ignore(gitignore 匹配标准库,零传递依赖;AGENTS.md 记录例外)。
- 测试:copy provider 新增 gitignore 根/嵌套/取反/开关、文件数/墙钟预算、
  预算内不误伤、signal 中止共 12 例;settings-schema 边界新增 2 例。
- 文档:五语 README 配置表与说明、CHANGELOG Unreleased、ARCHITECTURE
  D18/D19、AGENTS.md 布局与依赖例外同步。
@IMJoyJ
IMJoyJ force-pushed the fix/copy-gitignore-and-budget branch from 3ab4778 to 2f6860e Compare September 27, 2026 09:21
rebase 到 upstream 0.6.18 后上游 JSDoc 类型变精确,原 PR 侧新增代码
(copy 预算/中止、gitignore、mutationCheckpoint 节流)需补类型注解:
copy 构造器用局部变量收窄、预算 getter 标 undefined、walk 恢复
ManifestFile 注解、catch 处 error code 显式转换、ignore 读取器双参签名。
turn/end 取消词汇按两代宿主兼容:0.1.7 用 aborted|interrupted,
旧宿主行保留 cancelled(字符串比较)。
测试侧沿用 assertSnapshot 惯用法补非空断言,删 copy 构造器不存在的
maxSnapshotBytes 死选项;pnpm-lock 前滚到 rc.2 并纳入 ignore 依赖。
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