Repository navigation
Cut the gate to 7 s and a gh round trip from each plan write - #95
Merged
DocksDocks merged 5 commits intoOct 23, 2026
Merged
DocksDocks merged 5 commits into
DocksDocks merged 5 commits into
Conversation
ci-background-task.test.mjs held the whole suite's wall time: its two blocking tests ran a 2.5 s and a 3 s busy loop one after the other inside a single worker, so --parallel=4 could not help (#89). - The blockers now sleep. spawnSync already freezes the parent's event loop, so a busy loop adds nothing but CPU starvation of the measured child (the flake in 692c061). - The windows shrink with their margins kept: a 300 ms child behind a 1000 ms block (tolerance 250 ms), and a 1500 ms block with a 750 ms threshold for the 8 MiB writer, which took at most 190 ms under 4-core load. A startTask mutant that relays the child's pipes and times the await still fails both tests. - The two tests move to their own registered files so the parallel runner can place them on different workers. - The vacuity files start every gate at module load and await each result, instead of running 7 and 4 gates one after another. Measured on 4 cores: 6.43 s -> 1.72 s, 72 of 72 tests passing. Refs #89
scripts/tests/plan-cli.mjs ran about 32 cases in one process against one shared fake-gh state and one scratch repository, so its 198 plan.mjs starts ran strictly in series: 12.4 s, about 95% of each plugin gate (#89). Each case is now a node:test test with its own context (scratch repo, fake-gh state seeded with the plan labels, environment), built by scripts/tests/plan-cli/harness.mjs. The 44 cases sit in 9 files balanced by measured cost, and Node's runner gives each file its own process. The frozen-steps case and the status-transitions case that reused its plan are one test. scripts/tests/plan-cli.mjs stays the entry, so the gate invocation, the targeting call counts, the test-contract registry, and the validator-table row do not change; it runs the case files with --test-concurrency set to the available parallelism. plan.mjs still runs on Node through process.execPath. A new case pins the contract's list order (open plans first, then closed, each ascending) over a mixed state. The shared state used to exercise that path only by accident; plan.mjs line coverage stays at 996 of 1006 lines. Measured on 4 cores: 12.4 s serial -> 3.9 s. Refs #89
Every plan.mjs write ran four gh processes: the snapshot, a pre-write `gh issue view`, `gh issue edit`, and a read-back `gh issue view`. `list` ran a repository lookup and then `gh issue list` (#89). - A write now sends one `gh api graphql` request. Its first mutation, updateIssue, carries the body and any claim, so the body and the claim succeed or fail together. Label repair follows as discrete add and remove mutations: a full labelIds list would drop a label added concurrently, which gh avoids for the same reason. The last mutation returns the stored state, which replaces the read-back. - The pre-write read stays: the contract requires it and a case tests the race. Retire still closes only after its label write checks out. - The body travels as `-F body=@<file>`. gh fills `{owner}`, `{repo}`, and `{branch}` in any other -F value, so a quoted token would be stored rewritten; an @ file is sent byte for byte. - `list` reads the repository's plan issues in one paged query. - A status write on a repository that lacks a phase label now creates it, as `new` does, instead of failing inside `gh issue edit`. On GitHub: a status write takes about 2.8 s instead of 3.2 s, and `list` about 0.6 s instead of 1.3 s. Refusal strings and the contract are unchanged. The fake gh now mirrors gh's -F handling (an @ file is verbatim, other values are converted and placeholder-filled), so the plan-CLI suite catches a body sent the wrong way. Refs #89
- The write mutation no longer selects the stored assignees. No check reads them, so the field only added a way for a write to fail. - REPOSITORY_LABELS stays a joined string, as before. - sharedFilesAdvice and printAdvice get their original formatting back; the change does not touch them, and the gate does not format this shipped file. Refs #89
Code review round 1 on #89: the write path took the label names to remove from the snapshot, which pages every label, but took their ids from `gh issue view`, which reads only labels(first:100). A phase label past the first 100 got no removal id: `status` wrote the body, kept both phase labels, and refused afterwards; `archive` and `retire` on an owned plan returned early without the label check, so archive reported success and retire closed the issue with the label attached. The released helper removed by name through `gh issue edit`, so this was a regression. - The snapshot now reads label ids with the names, and the removal ids come from that complete list. The pre-write read drops labels. - The early return for "nothing left to change" is gone: names and ids now come from one list, so it could not be reached, and it was the path that skipped the label check. - The fake gh truncates `issue view` labels at 100, as real gh does. With that, the paged-label status case and a new archive case fail on the previous commit and pass now. Refs #89
This was referenced Oct 23, 2026
DocksDocks
deleted the
89-optimize-the-gate-and-the-plan-helper-after-the-bun-switch
branch
October 23, 2026 14:43
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.
Yolo run: #89 Optimize the gate and the plan helper after the Bun switch
Pull request: #95. Checks: all 5 pass. Reviewed head:
1b2fe575.What changed
scripts/tests/unit/,scripts/config/test-contracts.json)scripts/tests/plan-cli.mjsstays the entry, so the gate, the targeting contracts, and the registry do not change. A new case pins thelistorder. (scripts/tests/plan-cli/,scripts/tests/plan-cli.mjs)plan.mjs: each write sends one GraphQL request instead ofgh issue editplus a read-back.updateIssuecarries the body and any claim, and discrete label mutations follow.listuses one paged query. Writes go from 4 gh calls to 3,retirefrom 5 to 4, andlistfrom 2 to 1. Refusal strings and the contract do not change. (plugins/plan-lifecycle/skills/productivity/plan-manager/scripts/plan.mjs)-Fhandling (an@file is sent verbatim; other values are converted and get placeholders filled) and gh's 100-labelissue view. (scripts/tests/fixtures/gh-stub/gh)Decisions and corrections
-F body=@<file>. gh fills{owner},{repo}, and{branch}in any other-Fvalue, so a body that quotes them would be stored rewritten (cli/clipkg/cmd/api/fields.go).labelIdslist. A full list would drop a label that someone adds at the same time, and gh avoids this on purpose (cli/clipkg/cmd/pr/shared/editable_http.go).scripts/ci.mjsand the workflow stay as they are. Overlapping checks would save only about 2 to 4 s more and would touch the timing and targeting contracts.plan.mjsstart).Reviews
Plan review passed in round 3. Rounds 4 and 5 passed again after two one-sentence changes to Research. Code review passed in round 2.
Open findings: none. Round 1's two MEDIUM findings had one root cause, label removal IDs taken from the 100-label
gh issue view, and commit1b2fe575fixes it.Verification
origin/mainagainst this branch, both on Bun (medians of 3 interleaved runs, the gate's owntotal_ms):origin/main--plugin plan-lifecycle--lane repotaskset -c 0-3):bun run test:unittakes 1.73 s instead of 6.43 s, andnode scripts/tests/plan-cli.mjstakes 4.1 s instead of 12.4 s.listtakes 0.51 to 0.78 s instead of 1.10 to 1.42 s, and astatuswrite spends 2.76 s in gh instead of 3.23 s (medians).bun scripts/ci.mjsandbun scripts/tests/ci-plugin-targeting.mjsexit 0. The unit suite passes 72 of 72, the plan-CLI suite 48 of 48, andplan.mjscoverage is 99.54% of lines.retire4. The claim, the phase labels, and a body that quotes placeholder tokens were all stored correctly.total_msfrom the timing artifacts): the core lane's gate took 9.4 s instead of 18.1 s on Run the repository's author tooling on Bun 1.4.4 #88, and the repo lane's gate took 6.5 s instead of 10.0 s. The jobs took 29 s (core), 23 s (repo), and 29 s (targeting contracts), against 39 to 40 s, 31 s, and 42 to 55 s on Run the repository's author tooling on Bun 1.4.4 #88 and yolo: archive only on Merge now when the answer starts a new run #86.Limits and failures
plan.mjsspeedup reaches users only with the next plan-lifecycle release. This plan makes no release.planlabel is removed, solistdoes not show them.workflow_dispatchrun onmain(39885296173) passed and covers the dispatch leg.Kept resources
Merge now: the review scratchdocks-review/yolo-89in the main checkout's git directory (benchmarks, research logs, probes), and probe issues Probe: plan.mjs GraphQL write path (#89) #91 to Probe: plan.mjs label removal by snapshot id (#89) #94 (closed). No worktree or process remains.Leave pull request open: also the local and remote branch89-optimize-the-gate-and-the-plan-helper-after-the-bun-switch.After merge
Closes #89