Repository navigation
fleet-write: the executor applies write-pace rule ⑤ to a stroke of 5+ content-creating actions, and the seat budgets for it - #24810
Merged
objectstack-fleet[bot] merged 3 commits intoOct 20, 2026
Conversation
The executor announces ONE rule-5 batch before the first write when a stroke carries DEFAULT_BATCH_THRESHOLD or more content-creating actions, so those writes leave DEFAULT_BATCH_GAP_MS apart instead of rule 1's 3 s. The content-creating set is read off the op table (createsContent), the pacing has one spelling (strokePacing) shared by the packer, the run-poller and the executor; a stroke whose pacing the relay job cannot hold is refused at the packer and again at the executor with zero writes, naming the per-op doors; the seat waits for a batched run as long as the runner is told to pause. Claude-Session: https://claude.ai/code/session_01HEdP5tPhqQfzwRmKDxwn85 Co-authored-by: Claude <noreply@anthropic.com>
…fusal as an exit, never a crash Claude-Session: https://claude.ai/code/session_01HEdP5tPhqQfzwRmKDxwn85 Co-authored-by: Claude <noreply@anthropic.com>
…troke, and pin the transcript line's order without a vacuous pass Claude-Session: https://claude.ai/code/session_01HEdP5tPhqQfzwRmKDxwn85 Co-authored-by: Claude <noreply@anthropic.com>
Contributor
Author
维护者速读(终稿)· PR #24810 ·
|
This was referenced Oct 20, 2026
objectstack-fleet
Bot
deleted the
claude/issue-24755-relay-stroke-batch-gap
branch
October 20, 2026 08:26
This was referenced Oct 20, 2026
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.
Fixes #24755
Clause-②: no
What this changes
The relay executor (
scripts/pm/fleet-write/execute.mjs) now applies write-pace rule ⑤ itself. When one stroke carriesDEFAULT_BATCH_THRESHOLD(5) or more content-creating actions, it announces ONE batch on the runner (announceBatch, kindfleet-write stroke) after the sender gate and before the first write. The writes from the first through the last content-creating one then leaveDEFAULT_BATCH_GAP_MS(30 s) apart instead of rule ①'s 3 s. Below the threshold nothing changes.Seat side (
scripts/pm/fleet-write/dispatch.mjs). The packer, the run-poller and the executor all read the same definitions:CONTENT_CREATING_OPSis derived from the op table bycreatesContent, never listed. It is an op whose first request is a RESTPOSTcarrying prose (title/body), or one that creates or moves a card (ANNOTATED_OPS). Today that iscomment,issue_create,pr_createandtransfer. Edits, label / assignee / reviewer writes, the ready / auto-merge flips, the base sync and the workflow dispatch do not count.strokePacing(payload)returns:DEFAULT_BATCH_GAP_MS;RELAY_JOB_TIMEOUT_MSlessDEFAULT_CEILING_MS:RELAY_JOB_TIMEOUT_MSmirrors the relay job'stimeout-minutes: 10. The self-test pins it to.github/workflows/fleet-write.yml.DEFAULT_CEILING_MS(5 min) is the allowance an ordinary stroke already has from dispatch to completion.packRequestrefuses a stroke whose pacing is over the budget, for every sender and before anything leaves. The refusal names the per-op doors (issue-create.mjs,post-stamped.mjs,issue-transfer.mjs,close-cards.mjs,label-write.mjs) behind onewrite-pace.mjs --announce-batch N. The executor refuses such a stroke again, with zero requests (exit 2), in case a sender skipped the packer.sendFleetWriteadds the stroke's pacing to its completion ceiling and prints one line saying so. A batched stroke is waited for. It is never reported UNCONFIRMED for pausing as it was told to.paceWriteapplies.scripts/pm/write-pace.mjsis only read:announceBatch,DEFAULT_BATCH_THRESHOLD,DEFAULT_BATCH_GAP_MS,fmtDuration,unrecordableTextandpaceFilePath. The workflow is untouched.Reach
Relay run https://github.com/objectstack-ai/objectstack/actions/runs/39369675259 was created at 2026-10-20T04:27:32Z and completed at 04:28:28Z. It created 15 issues on objectstack-ai/objectui:
That is 15 cards in 42 s from one identity. The job spent 11 s before its first write. All times are read from the run and from the issues'
created_at.Runtime against the two ceilings
issue-create.mjsbehind--announce-batch 15MAX_ACTIONS)A landing stroke (
pr_ready+automerge_enable) carries no content-creating action. Every per-op door sends one card per stroke, with at most one. Neither changes.Tests (HEAD 4a9257f)
Each new self-test battery has a pinned case floor, and each file's battery-count floor is raised (execute 17, dispatch 21).
execute.mjs --self-test, battery "the batch gap on the runner" (10 cases, on an injected clock and a stubbed platform):issue_createactions in one stroke land with gaps[30000,30000,30000,30000]. Their sum equalsstrokePacing'spacingMs.dispatch.mjs --self-test, battery "the batch gap at the seat" (13 cases):strokePacingat, below and above the threshold, counting a pull's label leg.maxBatchWritesthe packer refuses and the CLI exits 2. AtmaxBatchWritesthe stroke packs.RELAY_JOB_TIMEOUT_MSequals the workflow'stimeout-minutes.success, and the ceiling grew by exactly the pacing. The same run with an unbatched stroke istimeout.Results:
executedispatchvalidatewith-fleetReverse mutations, each through
scripts/ablation-replace.mjs. Each mutation landed (anchor hits 1 then 0, blob changed) and was restored (blob equal to HEAD,git diff HEADempty). Every one turned the self-test red:announceBatch(...)call[3000,3000,3000,3000](re-run on 4a9257f)timeoutat 300000ANNOTATED_OPSarm ofcreatesContenttransferdropped out of the setGates (HEAD 4a9257f)
node scripts/pm/dispatch-gates.mjs --commandsderived 40 commands for this diff, the same as the dispatch order's list. All 40 exited 0,pnpm check:pm-dispatch-gatesincluded (fast tier, 1913 cases). Running--ranwith every exit code recorded reported40 derived, 40 run, 0 NOT-MEASURED, 0 UNRUN. Every other family is CI's.Acceptance notes
validate.mjs'sstrokeErrors. It is a rule about the run's pacing, not the payload schema, andvalidate.mjscannot import the seat's ceiling without an import cycle. As a result, an over-budget stroke on the runner is refused by the execute step (zero writes, exit 2, summary written), not by the validate step.--payload-filerun on a persistent home would keep the batch until its own expiry at most, the same as any early-stopping--announce-batchcaller.sendFleetWritewaits for each run before returning. For a batch, the contract is still the seat-side--announce-batchin front of the per-op doors; a directdispatch.mjsstroke is for landing. Noted, not filed.origin/main. That commit, a43405d, is a one-line doc edit to.claude/skills/pm-dispatch/references/filing-gate.mdand does not overlap this diff, so it was not merged in. The queue rebuilds on current main.维护者速读(草稿)
改了什么:中继(fleet-write)执行器在同一笔里含 5 个及以上"创建内容"的动作(新建 issue、评论、PR、转移卡片)时,先在 runner 上宣告批次,随后这些写入每次间隔 30 秒(write-pace 规则 ⑤)。发送端用同一公式算出这笔会暂停多久,相应延长等待;超出中继 job 10 分钟预算(单笔最多 11 个批次写)的笔在发送前被拒,并指向逐 op 工具。
为什么改:两个席位账号曾因短时间大量创建内容被平台限制,规则 ⑤ 正是为此加的截流;但中继路径漏了这道闸 —— 10-20 当天一笔 15 张卡 42 秒内落完。
风险与代价(含回滚):一笔 5 张卡现在约需 2 分钟、11 张约 5 分钟,这是设计,不是变慢;单笔超过 11 个批次写会被拒,需改走逐 op 工具加
--announce-batch。落地笔(ready + automerge)与逐 op 工具的单卡笔不受影响。回滚:revert 本 PR 即恢复 3 秒间隔。席位意见:
你要做的:无需操作;
scripts/pm/**非受管面,席位 ACCEPT 后翻 ready 入队。Generated by Claude Code