Repository navigation
fix: 并发/重复调用导致目录卡出多个同名空壳《第二章》章卡 - #24
Merged
Merged
Conversation
A runaway agent turn (repeated parallel create calls or parent/child subagents creating the same chapter) could stack several empty same-named chapter cards in the manuscript directory, because: - allocateStableId seeds ids per tool call, so every duplicate create got a fresh id and never collided; - the same-run proposal overlay did not remember chapter.create, so preflight and id allocation never saw the pending chapter card; - chapter.create/chapter.update only validated id uniqueness, never title uniqueness within a volume. Fix in two layers: - contracts: applyChapterOperation now rejects chapter.create and title-renaming chapter.update when the same volume already holds a chapter card with that title (already_exists). This guards every path: agent tool preflight, renderer structure mutations and the Core apply side. - pi-runtime-adapter: the proposal overlay now remembers chapter.create operations and projects them into the same-run index view, so a repeated create inside one run (including across parent and child agents sharing the run state) fails preflight immediately with the existing friendly already_exists guidance instead of forming another proposal card. Titles stay free across volumes, and distinct titles in one volume are unaffected.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
问题
智能体一回合内重复(或并行子智能体同时)调用
create kind=chapter_card时,目录里会一口气出现好几个重复的、空壳的同名章卡(例如多个《第二章》),全部是空正文。根因(三层叠加)
allocateStableId的种子是${bookId}:${runId}:${toolCallId}(long-agent-tools/shared.ts)。每次重复调用 toolCallId 都不同 → 每次都分配到新 ID,assertNewEntityId的already_exists防线永远触发不了。createProposalOverlay().remember()(long-agent-tools/proposal-overlay.ts)只记录storyPlot.create和两类 continuity 创建,不记录chapter.create。于是同一 run 里第二次创建章卡时,loadIndex返回的索引看不到第一次的待审章卡——预检通过、排序照常 +1,又形成一张新提案卡。父/子智能体共享 overlay 也一样中招。apply-chapter.ts的chapter.create/chapter.update只做 ID 唯一性校验,同卷同名完全放行。执行层面
create工具本身是executionMode: "sequential"(且批次内任一 sequential 工具会使整批串行),所以"失控"并不是真并行 race,而是模型一回合重复发相同调用 + 上述三层缺口让每次重复都成功落卡。这与仓库既有约定一致——workspace.ts提示词已要求"创建前必须排除目录中已经存在的同名章节",短篇通道 accept 时也有同名检查(draft-section-lane.ts),唯独长篇章卡路径漏了。修复(两层)
contracts(
apply-chapter.ts):chapter.create与改名chapter.update增加同卷同名校验,冲突抛already_exists。预检(previewLongWorkspaceOperations)与落盘(Core apply)共用这段逻辑,因此智能体工具预检、界面结构变更、Core 应用三条路径都被守住。pi-runtime-adapter(
proposal-overlay.ts):overlay 开始记录chapter.create并把它投影进同 run 的索引视图(plot.chapterCards+chapters)。同一 run 内(含父子智能体共享状态)的重复创建会在预检阶段立刻得到既有的友好提示:"未形成长篇结构变更提案:目标条目已经存在(already_exists)……不要重复提交相同参数",不再生成第二张提案卡。行为边界
already_exists)测试
long-agent-tools.duplicate-create.test.ts:同 run 重复创建被拒(含父子智能体共享 overlay 场景)、不同标题正常创建。long-workspace-operations.chapter-title-uniqueness.test.ts:contracts 层同卷同名 create 拒绝、跨卷同名允许、重命名冲突拒绝/改新名允许。pnpm typecheck、pnpm lint(含边界检查、i18n)、pnpm format:check均通过。