Repository navigation
fix(deps): take the fixes for sharp and shell-quote that turn main's OSV scan red - #22016
Conversation
…OSV scan red sharp GHSA-wq5f-xc86-pv6w (fixed 0.35.5): lift the existing override's target from ^0.35.4 to ^0.35.5; the <0.36.0 selector already sits at the 0.x caret boundary. next@16.3.6's optional ^0.35.4 admits it, so this is a dedupe onto the patched line. shell-quote GHSA-pqg4-j6r4-53mv (fixed 1.11.0): a new override 'shell-quote@>=1.8.4 <2.0.0': '^1.11.0'. The one path is launch-editor 2.14.1 (^1.8.4) <- @changesets/cli 3.0.3, and no release up that path forces the fix, so no bump can replace the floor. The lockfile moves only sharp, its @img/sharp-* binaries and shell-quote. Claude-Session: https://claude.ai/code/session_01VF48aw8RPG6wzDnMgp6rtw Co-authored-by: Claude <noreply@anthropic.com>
|
Cross-lane note from The red |
…v-sharp-shell-quote Re-run CI on a fresh head after Type Check · source gates was cancelled at its timeout during checkout. main brought no dependency file change. Claude-Session: https://claude.ai/code/session_01VF48aw8RPG6wzDnMgp6rtw Co-authored-by: Claude <noreply@anthropic.com>
|
Merge-queue ejection, not this PR's: re-queued once · seat
Generated by Claude Code |
…to a checkout budget plus a body budget (objectstack-ai#22033) Fixes objectstack-ai#22020 Clause-②: no ## Which route The card's done-when offers two routes. This PR takes the first one, in the split form triage asked for (`6022336293`). Every full-history checkout under a fixed job wall gets its own step-level `timeout-minutes: 20`. Each job wall becomes that checkout budget plus the job's re-measured body budget. No gate, command, fetch depth, job id or check name changes. The seven required contexts are untouched, and the merge-base anchor of the authorable-surface deletion gate keeps its full history (`fetch-depth: 0` is unchanged on every job). | job | file | wall before | checkout step | body budget | wall after | |---|---|---|---|---|---| | Type Check · source gates (the card) | `lint.yml` | 10 | 20 | 10 | **30** | | Type Check · workspace (adjacent) | `lint.yml` | 30 | 20 | 35 | **55** | | Type Check · debt ledger (adjacent) | `lint.yml` | 15 | 20 | 15 | **35** | | Type Check · consumer gates (adjacent) | `lint.yml` | 20 | 20 | 25 | **45** | | Governed Surface Queue Guard (adjacent) | `governed-surface-guard.yml` | 10 | 20 | 10 | **30** | **In-scope adjacent fixes.** All four have the same defect class and get the same mechanical treatment: - The other three Type Check lanes, added by the PM after merge-group run 37509811445. In that run, job 112427734781 ("Type Check · consumer gates") spent 11m05s in the checkout and was cancelled at its 20-minute wall. The aggregate failed and PR objectstack-ai#22016 was ejected from the queue. - The Governed Surface Queue Guard, which the claim named (run 37508992265, job 112424902156). The `lint` job is not touched. Open PR objectstack-ai#22002 edits its region. ## Measured **Window.** I read the 300 most recent completed runs of `Lint & Type Check` (2026-10-05T15:32Z to 2026-10-06T18:41Z) and of `Governed Surface Guard` (2026-10-05T14:57Z to 2026-10-06T18:59Z). Every attempt was included (`GET /actions/runs/{id}/jobs?filter=all`), using step timestamps. The controls come from the 300 most recent `CI` runs (2026-10-05T15:15Z to 2026-10-06T18:22Z). **Checkout per job.** "Wall hits" counts the runs that the old wall cancelled behind a slow checkout: | job | n | p50 | p90 | p99 | max | wall hits | |---|---|---|---|---|---|---| | Type Check · source gates | 293 | 31 s | 122 s | 599 s | 600 s (cut by the wall) | 8 | | Type Check · workspace | 296 | 31 s | 100 s | 395 s | 421 s | 0 | | Type Check · debt ledger | 293 | 31 s | 123 s | 599 s | 774 s | 2 | | Type Check · consumer gates | 293 | 31 s | 151 s | 574 s | 735 s | 2 (both `merge_group`) | | Governed Surface Queue Guard | 292 | 31 s | 156 s | 595 s | 599 s (cut by the wall) | 4 | **Pooled.** Adding the same fetch from `ci.yml`'s Test Core shards gives n = 3,459: p50 31 s, p90 119 s, p99 553 s, max 895 s. Another 19 samples were cut off by a wall and are lower bounds only. **Control.** The shallow (`fetch-depth` 1) checkouts in `ci.yml` over the same hours (n = 2,743) read p50 15 s, p99 63 s, max 107 s. None went over 180 s. So the slow tail belongs to the full-history fetch, not to the runner pool. **Body budgets.** The body is everything after the checkout, on successful runs: | job | max | 2 × max | budget | |---|---|---|---| | source gates | 3.2 min | 6.4 | 10 (the floor) | | workspace | 17.9 min | 35.8 | 35 | | debt ledger | 7.4 min | 14.8 | 15 | | consumer gates | 11.5 min | 23 | 25 | | guard | 1.1 min | 2.2 | 10 (the floor) | The rule is the `lint` job's: 2× the measured max, on a 5-minute grain, never below 10. **Checkout budget.** 20 minutes is 1.3× the pooled 895 s max. The rule's 2× would give 30, but the queue's window binds first: the workspace lane's 35 plus 30 is 65, past the 55 cap the `lint` job argues, while 35 + 20 = 55. It is one fetch, so every job gets the same budget. ## What the required aggregate reads **Before.** The lane's job wall stopped any checkout that left the body too little time. That covers slow checkouts that would have finished, such as the 555 s and 588 s cases, as well as stuck ones. The lane read `cancelled` and every gate was skipped. `TypeScript Type Check` printed "concluded `cancelled` -- expected `success`" and failed the PR. **After:** - **A checkout that ends inside 20 minutes:** nothing happens. The body keeps its full budget and the lane goes green. In this window, that covers every checkout that completed. - **A checkout still running at 20 minutes:** the step fails with "The action 'Checkout repository' has timed out after 20 minutes." Later steps are skipped, the lane reads `failure` and the aggregate goes red. No layout can keep a truly hung checkout green, because the aggregate correctly refuses a lane that ran no gate. This layout names the step that hung, and it fires only beyond 1.3× anything measured. - **A later step that hangs:** the job wall cancels the job, the lane reads `cancelled`, and the aggregate goes red, as before but at the new wall. **Source check (premise 2).** In actions/runner `main` at `67f01c27`, `StepsRunner.RunStepAsync` evaluates every step's `timeout-minutes`, `uses:` steps included. When it expires, the runner sets `TaskResult.Failed` with that message. A job-level cancellation sets `TaskResult.Canceled` instead. No workflow in this repo had a step-level timeout before this PR. ## Deviation from triage's direction Triage wrote: "The gate steps keep the stall guard's intent through their own step-level timeouts." I did not add those. The PM thread has the reasoning: - Actions has no timeout over a group of steps. Covering the gates would take one step-level timeout per step, about 65 of them across the four lanes, each sized from a single 27-hour window. - Several of those steps are bimodal, for example a turbo cache hit in 4 s against a miss in 5 minutes. Timeouts sized that tightly would be a new source of random reds, which is this card's own defect class. The cost: after a fast checkout, a hung gate now runs up to the new wall (30, 35, 45 or 55 minutes) instead of the old one. Every new wall stays at or under the 55 cap, inside the queue's 60-minute window. ## This PR's own lane run Read from the jobs API by the seat (step timestamps), run `37519814891` (`Lint & Type Check`, head `f5060b251`) and run `37519814823` (`Governed Surface Guard`): | job | conclusion | checkout | job duration | new wall | |---|---|---|---|---| | Type Check · source gates | success | 34 s | 197 s (3.3 of 30 min) | 30 | | Type Check · debt ledger | success | 147 s | 217 s | 35 | | Type Check · workspace | success | 242 s | 280 s | 55 | | Type Check · consumer gates | success | 33 s | 298 s | 45 | | TypeScript Type Check (aggregate) | success | — | 3 s | — | | Governed Surface Queue Guard | success | 38 s | 66 s | 30 | _Section filled in by the `domain:devx` seat 2 PM from the run above, because the body is written before its own run exists._ ## Local gates (head `f5060b251`) `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` derived 44 commands from the actual diff. Exit codes were written to disk before reading: - 42 exit 0. This includes `check:required-contexts`, `check:stall-guard-budget`, `check:stall-guard-headroom`, `check:workflow-status-functions`, `check:workflow-step-name-quoting`, `check:aggregator-roster` (+ `--self-test`) and `check:step-collectors` (+ `--self-test`). The full reconciliation is in the report. - I also ran the guard's own `check-governed-queue-guard.mjs --self-test`: 296 cases passed, including the `fetch-depth: 0` pin. - `check:type-check-debt` ran its `--self-test` half (exit 0). Its `--re-measure` half needs the workspace build the debt lane runs first. It is declared to this PR's CI rather than measured here, because the diff touches no package and no ledger. ## Acceptance notes - **Mechanism, measured locally and not changed here.** `fetch-depth: 0` makes actions/checkout v7 fetch `+refs/heads/*` and `+refs/tags/*`: 1,236 branch heads and about 7,950 tags today. From this container: | fetch | time | pack | |---|---|---| | `main`'s full history alone | 29 s and 32 s | 397 MB | | the all-refs refspec CI uses | 473 s | 598 MB | | all heads without tags | 686 s | 597 MB | | depth 1 plus unshallowing `main` | 120 s and 169 s | not recorded | The last variant kept the anchor exact on PR objectstack-ai#22002's merge ref and on PR objectstack-ai#6356's old head. The cost is the ref set, not `main`'s depth. Fetching less could make every one of these jobs faster, but the CI tail of any narrower fetch is unmeasured (n = 0), and its semantics need a per-gate audit across all five jobs. It is left as a question for the PM in the report. - **`ci.yml` Test Core shards**, same fetch, 45-minute wall: one shard was cancelled at the wall behind a 508 s checkout in the window (run 37338337323, `Test Core (2/6)`). This is outside this PR's file surface, and those steps run under the stall guard, whose budget gate reads that wall. The report names it for the seat. - **`Lint & Repo Gates`** is not exposed in the window: body max 34.5 min plus checkout max 730 s is 46.7, under its 55. --- _Generated by [Claude Code](https://claude.ai/code/session_01VF48aw8RPG6wzDnMgp6rtw)_ Co-authored-by: Claude <noreply@anthropic.com>
… (ruling 208) (objectstack-ai#22002) Fixes objectstack-ai#21959 Clause-②: no Deletes the report-only widening-tell instrument `scripts/pm/check-widening-tells.mjs` (6,528 lines) with all of its wiring, under ruling 208 (report-only instruments get no dev; their only in-flight work is deletion) and the maintainer's answer to decision batch 2 item 2, verbatim 「同意」. ⛔ Nothing replaces it, no gate is added, no workflow step is added. ## What changed — the full list (12 hunks in 8 files; nothing outside them) Line numbers are at base `6befe19c` (`origin/main` when the worktree was cut). | # | where (base) | before | after | |--:|:--|:--|:--| | 1 | `scripts/pm/check-widening-tells.mjs` | the instrument, 6,528 lines | deleted | | 2 | `package.json:85` | the `check:pm-widening-tells` script | removed | | 3 | `.github/workflows/lint.yml:1324-1336` | the "Widening-tell gate self-test" step with its 10-line comment | removed | | 4 | `.github/workflows/lint.yml:1693` | "same split as the widening-tell and prior-ruling steps above" | "same split as the prior-ruling step above" (bounded in-place fix, see below) | | 5 | `scripts/pm/measurement-claim-triage.mjs:57-62` | scope docblock names two excluded files | names only `scripts/pm/dispatch-gates.mjs` | | 6 | `scripts/pm/measurement-claim-triage.mjs:122-125` | `EXCLUDED` row for the instrument | removed | | 7 | `scripts/pm/check-half-states.mjs:1336-1339` | docblock says the register is the instrument's `SCHEMA_PROPERTY_FORMS` | the register is described on its own terms; no file or constant named | | 8 | `scripts/pm/check-prior-rulings.mjs:215-217` | comment says the instrument takes the same import | clause dropped | | 9 | `.claude/skills/pm-dispatch/references/instrument-discipline.md:7` | 放宽 tell(C5)由 `scripts/pm/check-widening-tells.mjs` 印 file:line,归达档复核裁。 | 放宽 tell(C5)不设仪器,Clause-② 的方向由达档复核裁。 | | 10 | `.claude/skills/pm-dispatch/references/instrument-discipline.md:6` | 判意图的仪器(放宽 tell、半状态巡查)… | 判意图的仪器(半状态巡查)… (bounded in-place fix, see below) | | 11 | `docs/audits/gate-census-2026-09.md:246` | verdict `retire` | `retire` · **deleted 2026-10** (ruling 208; 「同意」) — row kept | | 12 | `docs/audits/gate-census-2026-09.md:353` | retirement-list row | same row, marked **deleted 2026-10** — row kept | `instrument-discipline.md` stays at 12 lines (both edits are in place). **Bounded in-place fixes beyond the dispatch's list (rows 4 and 10).** Both are the same defect class as the card (a live sentence naming the deleted instrument), mechanical, in a file this PR already edits, and in the same gate family. Row 4: after row 3 the comment pointed at a step that no longer exists. Row 10: line 6 listed 放宽 tell as an existing intent-judging instrument. Without this edit it would contradict the rewritten line 7 on the line below. ## Premise checks (the card body is a lead, not a spec) - **"`check-half-states.mjs` and `check-prior-rulings.mjs` import `SCHEMA_PROPERTY_FORMS` from it": false at base.** Probe `git grep -n -E "(import|from|require|import\()[^;]*check-widening-tells" 6befe19` returns exactly 1 hit, and that hit is a comment: `check-prior-rulings.mjs:215`. The control is the same shape on `check-half-states`. It returns 33 hits, real imports among them, `check-prior-rulings.mjs:218` and the instrument's own `:1484` included. Outside the instrument, `SCHEMA_PROPERTY_FORMS` appears only in the `check-half-states.mjs:1336` docblock. The import direction is the reverse of the card's reading. The instrument imported from `check-half-states.mjs`, `dispatch-gates.mjs` and `regen-artifacts.mjs`, and nothing imported from it. The "move the constant" item therefore became rows 7–8, which rewrite the two comments. No code moved. - **Pin, "a repo-wide grep returns only historical changelog lines":** `git grep -n -E "widening-tells|SCHEMA_PROPERTY_FORMS"` over the whole tree at HEAD returns 4 lines, and none is in a CHANGELOG. No CHANGELOG ever named it. The 4 lines are: census `:246` and `:353` (marked deleted, kept per dispatch), census `:398` (the historical drift paragraph, deliberately untouched) and `scripts/pm/dispatch-gates.mjs:3895`. That file is frozen by ruling 208: its own `--self-test` is green with the instrument gone (below), so the word stays. ## Verification (HEAD `95c510eb`, worktree `objectstack-issue-21959`) - `node scripts/pm/dispatch-gates.mjs --self-test` → `✓ dispatch-gates self-test: 1976 cases pass.` EXIT=0 (`nohup` + `tail --pid`) - `pnpm check:pm-dispatch-gates` → `✓ check:pm-dispatch-gates --self-test: the exit contract holds in all three directions.` · `✓ dispatch-gates self-test: 1976 cases pass.` · `the battery took 842.7s on this box.` EXIT=0. It ran under `nohup` + `tail --pid`. A first attempt inside my sequential runner hit that runner's own 540 s per-command timeout, so it was re-run on its own, and that run is the one recorded here. - `node scripts/pm/check-half-states.mjs --self-test` → `✓ check-half-states self-test: 4912 cases pass.` EXIT=0 - `node scripts/pm/check-prior-rulings.mjs --self-test` → `✓ check-prior-rulings self-test: 155 cases pass` EXIT=0 - `node scripts/check-self-test-wired.mjs` EXIT=0 and `node scripts/check-self-test-workflow-commands.mjs` EXIT=0. The three wiring pieces went out together. - `node scripts/check-scripts-symbol-anchors.mjs` → `3722 anchors across 281 scripts resolve` EXIT=0 - `pnpm check:pm-skill-ratchet`, `check:pm-skill-id-lint`, `check:pm-governed-prose`, `check:pm-governed-merges`, `check:pm-expected-skips`, `check:doc-authoring`, `check:nul-bytes`, `check:issue-citations` → all EXIT=0 - `node scripts/pm/measurement-claim-triage.mjs --self-test` → EXIT=1 **identically at base `6befe19c` and at HEAD**. The failure in both is `UNTRIAGED scripts/check-dts-references.mjs:74`, which predates this PR and is unrelated to it. The report run's only difference base→HEAD is the dropped `NOT SWEPT … check-widening-tells.mjs` line; the population is unchanged (`88 claim(s) over 49 file(s)`). The tool is not wired into CI. - `dispatch-gates --commands` (no paths; change set from the merge base) derived 82 commands. I ran all 82, plus the six the dispatch named on top: 80 EXIT=0. **NOT MEASURED** (exit 3, `PREREQUISITE NOT MET`, no `dist/` in a fresh worktree): `check:dts-closure`, `check:dual-build-cjs-loads`, `check:lean-entry-closure`, `check:sourcemap-no-sources-content`, `@objectstack/lint check:doc-formula-expressions`. Declared narrowing: these read built workspace packages, this diff touches no workspace package, and CI runs them. - `--ran` reconciliation: `✓ dispatch-gates --ran: 82 derived famil(ies) accounted for — 77 run, 5 NOT-MEASURED (5 DERIVED from a recorded exit 3).` 0 UNRUN. - Lint, run on the edited files only (a proved narrowing; the repo-wide `pnpm lint` belongs to CI). `eslint --no-inline-config --format json` on the 3 edited `.mjs` files: 3 files linted, 0 errors, 0 warnings, and none was reported ignored, so all 3 sit inside the config's population. Invariance: `eslint.config.mjs` never enables type-aware linting (no `parserOptions.project`, no typed rules). Nothing imported the deleted file. So this diff cannot move the verdict on any untouched file. ## Landing - Governed **Tier S** (`.claude/skills/pm-dispatch/references/instrument-discipline.md`). The PR stays draft until the seat's contract-tier review. - Changed lines are 6,580 (+17 / −6,563), over the 5,000 human-merge threshold (AGENTS.md §7 class c). Almost all of it is the one deleted file. - `skip-changeset`: nothing here ships in any package's `files[]` (`scripts/pm/**`, `.github/**`, `.claude/**`, `docs/audits/**`, root `package.json` scripts). ## Acceptance notes (observed, not filed) - `scripts/pm/dispatch-gates.mjs:3895` still lists `check-widening-tells` among "five" live prose mentions; four remain. The file is frozen and its self-test is green, so the mention was left. Carrier: none. - `measurement-claim-triage.mjs --self-test` has been red on `main` since before this PR (`scripts/check-dts-references.mjs:74` untriaged). The tool is report-only and unwired. Carrier: none. - `instrument-discipline.md` has no row in `check-skill-line-ratchet.mjs` `CEILINGS`, so no gate holds its line count. It is kept at 12 regardless. Carrier: none. - `.claude/skills/pm-dispatch/references/triage-duties.md:64` still names 放宽 tell among report-only instruments whose fix cards are closed on first touch. The rule stays true for any stray card about the deleted file, so it was left. Carrier: none. ## 维护者速读(草稿) **改了什么**:删掉一个只报告、不挡任何 PR 的 PM 内部检查脚本(放宽 tell 仪器,6528 行),连同它的 `package.json` 脚本行和 CI 里跑它自测的一步;再把仓里所有还点名它的地方改成不再指向一个不存在的文件(两处脚本注释、一处 CI 注释、一份工具的排除表、PM 技能的仪器纪律两行、门禁普查表两行标「已删」)。 **为什么改**:裁决 208 定了只报告的仪器在途工作只有删除;维护者在决策批 2 第 2 项答「同意」删它。它在普查窗口里零拦截,却每次 CI 都要跑自测、隔三岔五还要派人修。 **风险与代价(含回滚)**:不替换、不新增门禁;Clause-② 方向的判断回到达档复核席位手里(原本也是席位裁,脚本只是印读数)。相关自测与门禁本地均绿。回滚 = revert 本 PR 一次即恢复脚本与 CI 步。 **席位意见**: **你要做的**:本 PR 触受管面(Tier S)且改动行数超过 5000(几乎全是删一个文件),按规则需要一次授权 APPROVED 审阅后由席位落地;无需其它动作。 ## Synced: the parked red cleared (landing-operations §C, released) This PR was parked as a draft behind PR objectstack-ai#22016 (the OSV fix for objectstack-ai#22013) with an expected-red list for `Validate Package Dependencies`. The release condition was met: PR objectstack-ai#22016 merged into `main` as `289ff6d4`. The seat then ran the one `update-branch` that list named: head `fab444b4` is the merge of `main` `289ff6d4` into the reviewed head `95c510eb`, with no file authored by anyone; the net diff against `main` is unchanged (8 files, +17 / −6563, every added and removed line byte-identical to the reviewed diff). - **Checks on `fab444b4`:** 37 check-runs completed, 0 failures, 0 cancelled; the 4 skips are all in the expected-skips roster (`check-expected-skips --pr 22002` exit 0). `Validate Package Dependencies` is green on the fixed lockfile. - **Contract review on this head:** PASS, comment 6025638745 (successor to 6019414425 on `95c510eb`). - **What remains is the Tier H terminal:** the diff is over the 5000-line human-merge threshold (`check-governed-merges --pr 22002` exit 3), so this PR stays a draft until an authorized APPROVED from `os-zhuang` or `hotlong`; the seat then clears `needs-user-decision`, flips ready and arms auto-merge, and the PR lands through the queue. _Section written by the `domain:skills` seat 2 PM (`session_0181E4ZeZmWyknawnauxD2CE`); everything above it is the dev's._ --- _Generated by [Claude Code](https://claude.ai/code/session_0181E4ZeZmWyknawnauxD2CE)_ Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Steve Jobs <steve@objectstack.ai>
Fixes #22013
Clause-②: no
What this does
Validate Package Dependenciesruns OSV-Scanner againstpnpm-lock.yaml. Two advisories published on 2026-10-06 matchmain's lockfile, so every PR that touches apackage.jsoninherits a red that is not its own (PR #22002, run 37483796939, is the first measured), and the next scheduled scan will be red too. Both advisories name a fixed version, so this PR takes both fixes. There is no exemption:osv-scanner.tomlis untouched, because it is for advisories with no fixed release.PR #22002 is not touched here. Its
update-branchafter this lands is the PM's pointer to its holder.OSV reading: before and after
Measured locally with OSV-Scanner v2.3.8, the version
validate-deps.ymlpins, in offline mode (--offline-vulnerabilities --download-offline-databases). The OSV npm database was downloaded on 2026-10-06 at 16:36 UTC, after both advisories were published (13:40 and 13:43 UTC).mainat803764a3(exit 1). These are the two rows the card names:This PR at
d263b701(exit 0):No issues found. One vulnerability is filtered, the standingsprintf-jsexemption, unchanged. The scanner names nothing beyond these two advisories, so no third one has appeared since the card was filed.Changes
sharp: the override target lifts from^0.35.4to^0.35.5'sharp@>=0.34.0 <0.36.0': '^0.35.5'. The selector already sits at the 0.x caret boundary, so it does not change. This is the same shape as theValidate Package Dependenciesnow fails on every PR and will fail on main's next scheduled run — 15 advisories across 7 packages (2 Critical innext), all with fix versions, and no lockfile moved #16999 lift on this entry.next@16.3.6declares the optionalsharp: ^0.35.4, which already admits 0.35.5. 0.35.4 was the single resolved copy.@img/sharp-*binaries exactly, so they move to 0.35.5, and the libvips binaries move to 1.3.4.rsvg 2.63.2, the librsvg release the advisory names as fixed, and it renders a PNG.shell-quote: a new override,'shell-quote@>=1.8.4 <2.0.0': '^1.11.0'quote(), a line terminator in a string after a{ comment }token ends the comment, and the rest of that string runs as shell input. The range is introduced 1.8.4, fixed 1.11.0.launch-editor@2.14.1, then@changesets/cli@3.0.3, then the rootpackage.json'sdevDependencies. launch-editor declaresshell-quote: ^1.8.4, which admits the fix, so this is a dedupe onto the patched line. The copy sat on 1.10.0 through lockfile inertia.<1.11.0.^1.11.0floats to 1.12.0, the newest 1.x. launch-editor calls shell-quote in one place,parse()on the editor command (guess.js). 1.11.0 and 1.12.0 only teachparse()ANSI-C quoting and more operators. Seven editor command strings (code --wait, a quoted macOS path with-w,emacsclient -t -a ''and others) parse identically under 1.10.0 and 1.12.0. The vulnerablequote()is never called on this path. The fix is taken anyway, because the gate reads the lockfile, not the call graph.overrides:.Why an override and not a
@changesets/clibumpNo release on that path forces the fix (
npm view, 2026-10-06):@changesets/cli3.0.3 is npmlatest, which is the version the root already declares. Every 3.0.x declareslaunch-editor: ^2.14.1.shell-quote: ^1.10.0, which still admits the flagged 1.10.0.So the bump route does not exist, and a launch-editor bump would still leave the floor to lockfile inertia. On the four axes:
^1.11.0. Its cost is one more ledgered entry.check:override-consistency, and no re-lock can land below it. A bare re-lock with no floor, like fix(deps): take the fixes for proxy-addr, source-map-js and katex that turn main's OSV scan red #21951'sproxy-addrstep, leaves nothing to stop a later resolution from drifting back.Lockfile diff
pnpm-lock.yamlis +126/−125, re-locked bypnpm install, never by hand. Every changed line falls into one of four kinds:sharp,@img/sharp-*orshell-quotepackage or snapshot key;overrides:header lines, which are the sharp target and the new shell-quote entry.Nothing else moves. This was measured by attributing every changed line: after dropping the lines that name sharp or shell-quote, and the integrity lines under those keys, zero lines remain.
pnpm-workspace.yamlis +39/−1: the sharp target, its dated note, and the shell-quote entry with its note.pnpm why, before and after:sharp0.35.4 becomes 0.35.5, one version in both cases. The tree shape is byte-identical with the version masked: throughnext@16.3.6under@objectstack/docs(and the fumadocs packages), and through better-auth'snextpeer under@objectstack/plugin-auth.shell-quote1.10.0 becomes 1.12.0, one version in both cases:launch-editor@2.14.1, then@changesets/cli@3.0.3, then the root's devDependencies.Changeset
skip-changeset. The diff touchespnpm-lock.yamlandpnpm-workspace.yaml, both repo-root configuration, and neither is in any package'sfiles[]. sharp resolves under two importers:@objectstack/docs, which is private.@objectstack/plugin-auth, which is published. Itsfiles[]isdist,README.mdandCHANGELOG.md, and itspackage.jsondoes not change. It declares no sharp range at all. sharp reaches it only through better-auth 1.7.3's optionalnextpeer, which this workspace auto-installs (auto-install-peers=true), and next's own optionalsharpdependency.Overrides do not reach downstream installs, so nothing published changes. shell-quote is dev-only, under the private root.
Local verification, at
d263b701pnpm install --frozen-lockfile --prefer-offline: exit 0.node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, derived from the change set at this head: 22 commands. The dispatch named 25 because it includedpackage.json, which this diff does not touch. The--ranreconciliation is filled in below.--ranreconciliation, with exit codes recorded before any pipe: 22 derived, 18 run, 4 NOT-MEASURED, 0 UNRUN.node scripts/check-changeset-fixed.mjsnode scripts/check-closing-keyword-parity.mjs(+--self-test)node scripts/check-comment-mask-corpus.mjsnode scripts/check-dts-emitted.mjs --self-testnode scripts/check-osv-exemptions.mjs(+--self-test)node scripts/check-prerelease-pin-watch.mjs --self-test;--verbosepnpm --filter @objectstack/spec run check:llms-txtpnpm check:driver-memory-census·check:gitlink-declared·check:nul-bytes·check:override-consistency·check:refd-timer-probe·check:vendor-export-contract-resolve·check:watch-hint-literal·check:workspace-manifest-cyclespnpm check:dts-closure·check:dual-build-cjs-loads·check:lean-entry-closure·check:sourcemap-no-sources-contentcheck:override-consistency: the census now counts 38 overrides, up from 37. shell-quote appears in neither report: it has a consumer, and its bound clears the target floor.dist/. This diff touches no package source, so the local scope builds no package, and the build these four need is the fullpnpm build. CI'sBuild CoreandLint & Repo Gatesmeasure them on the built tree. This narrowing is declared here, and none of the four is counted as a pass.dispatch-gateslists (Test Core,Temporal Conformance,Dogfood Regression Gate,Dogfood Verify CLI,Build Core,Build Docs) and the type-check lanes.Acceptance notes
pnpm installprintsioredis-mock 8.13.1: unmet peer ioredis@^5: found 6.0.0. That warning is already onmainand is not from this diff.Generated by Claude Code