release(v18): enter Changesets pre mode on main (changeset pre enter next) with one major marker, so the first v18 prerelease is 18.0.0-next.0 — the opening ruled B on #22050 #22080
Description
Unblocks: #15194 (the ADR-0131 v18 epic). Its staged 18.0.0-next.N prereleases need Changesets pre mode on main.
Filing gate: ③ a maintainer-directed task. The ruling is B on #22050 (record 6037890422). The maintainer, in the triage seat's chat, verbatim: 「我建议直接启动 v18 开发吧」, 「你应该先解锁 v18 所有的卡片」, then 「同意」 to the execution plan. #15193, the v18 gate, closed on that word (6037915987), and the v18 cards it held were unlocked first, as ordered. Filed by the triage seat (objectstack-wide, seat post #6015, session_01AavokzJ5DndAwitDXvKy4U). ⛔ Not a claim.
Reader: domain:devx takes the PR. The merge is the maintainer's: it changes how every later release versions.
The change (one PR)
- Enter pre mode.
pnpm changeset pre enter nextcommits.changeset/pre.jsonwith"mode": "pre"and"tag": "next". - One
majormarker. Add one changeset that grades one member of thefixedgroupmajor. Its text is the v18 line's opening note (ADR-0131; ruled on decision: open v18 now and ship it in stages — release the last 17.x from main first without waiting for #21908's deny (A), skip the last 17.x (B), or keep #22009's order (C)? #22050).- Why it is needed: every publishable package is in the
fixedgroup (.changeset/config.json), which versions in lockstep at the highest pending bump. Every pending changeset onmainisminororpatch, so pre mode alone would version17.8.0-next.0. - The count: on
main879bd38c5b, this command prints14 : minorand30 : patch:for f in $(git ls-tree --name-only origin/main .changeset/ | grep '\.md$' | grep -v README); do git show origin/main:$f | sed -n '2,/^---$/p'; done | grep -oE ': *(major|minor|patch)' | sort | uniq -c. - Skip this step only if a
majorchangeset is already pending when the PR is cut. Say so in the PR body if you do.
- Why it is needed: every publishable package is in the
- ⛔ No edit to
scripts/check-changeset-no-major.mjs. Its RC EXEMPTION (:94) stands aside while.changeset/pre.jsonis in pre mode. Show that the PR passes it. If the guard readspre.jsonat the base rather than the head, land step 1 alone first, then step 2. - ⛔ No edit to
.github/workflows/release.yml. In pre mode,changeset publishpublishes under the pre tagnext, and npmlateststays 17.7.0. Quote the path that decides this in the PR body, from a reading of the file. ⛔ Do not run a publish.
Pins (in the PR body)
- In a throwaway worktree, never committed,
changeset versionputs thefixedgroup at18.0.0-next.0. check-changeset-no-majorandcheck-changeset-fixedpass on the PR..changeset/pre.jsonis present at the merge, with"mode": "pre"and"tag": "next".
After it lands
- The version PR. changesets/action refreshes chore: version packages (next) #21988 into the prerelease version PR (
18.0.0-next.0). Publishing it is the maintainer's approval, as with any release. Per decision: open v18 now and ship it in stages — release the last 17.x from main first without waiting for #21908's deny (A), skip the last 17.x (B), or keep #22009's order (C)? #22050, each18.0.0-next.Nis cut when an ADR-0131 stage completes.- ⛔ Until this card lands, chore: version packages (next) #21988 is not merged: it would publish v18's breaking stages as 17.8.0.
- The last pre-v18 commit. Triage records the last pre-v18
maincommit (this PR's merge commit's first parent) on decision: open v18 now and ship it in stages — release the last 17.x from main first without waiting for #21908's deny (A), skip the last 17.x (B), or keep #22009's order (C)? #22050 and [epic] ADR-0131 — total organization ownership: no NULL organization_id (v18 line) #15194.
Not in this card
changeset pre exitand the no-major guard's retirement. Both come at 18.0 GA, after C7 (feat(objectql,cli): inventory + migration — four fates per object, mirrors deleted only after the id→name rewrite is verified, per-table boot report (ADR-0131 D10) #15211) and cloud#1979, per the guard's own END CONDITION.- objectui's dependency. It stays on
^17until 18.0 GA (stated on decision: open v18 now and ship it in stages — release the last 17.x from main first without waiting for #21908's deny (A), skip the last 17.x (B), or keep #22009's order (C)? #22050). The console in v18 prereleases follows v18 through the build's spec injection (scripts/assert-console-spec-injection.mjs). - cloud's pin. It stays on
56bf27affbuntil cloud#1979.
Related: #22050 · #15193 · #15194 · #21988 · #22009 (the earlier opening line, superseded by #22050's B).
Activity
objectstack-fleet commentedon Oct 7, 2026
Claim: PM loop round 7
Session:
session_01VF48aw8RPG6wzDnMgp6rtwAccount:
os-justin(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-22080-v18-pre-mode(new, cut fromorigin/main3d9188502e)Worktree:
objectstack-issue-22080Domain:
domain:devxSeat:
domain:devx#2File surface:
.changeset/only..changeset/pre.json, written bypnpm changeset pre enter next.fixed-group membermajor: the v18 line's opening note (ADR-0131; B on decision: open v18 now and ship it in stages — release the last 17.x from main first without waiting for #21908's deny (A), skip the last 17.x (B), or keep #22009's order (C)? #22050).scripts/check-changeset-no-major.mjs,.changeset/config.jsonor.github/workflows/release.yml. ⛔ No publish, nochangeset versioncommitted.Container & model:
M,mode:subagent,model: opus(dispatch-gates --tier: no path-derived mandate; default tier)Clause-②: no
Responsibility:
n/a — not a defect card(a maintainer-directed release task, ruling B on decision: open v18 now and ship it in stages — release the last 17.x from main first without waiting for #21908's deny (A), skip the last 17.x (B), or keep #22009's order (C)? #22050)Thread-read: none
Serial constraints cleared: no open PR touches
.changeset/pre.json,.changeset/config.json, the two changeset guards orrelease.yml(all open PRs read: chore: version packages (next) #21988, feat(spec)!: the build doors refuse a builtin node config value its executor contract refuses, with its location #21974). In-flight claims feat(spec,services): deployment-level state has no organization column — settings global rung, plumbing objects, the audit ledger, #12699 made total (ADR-0131 D7) #15207, Phase 2 of #11333: retire the legacy string[] arm of manifest.permissions (major, standard retirement route) #13458 and ADR-0120 协议 18 项:D2 conversion(声明索引 unique: true → 'global')+ 裸 true 硬拒 + synonym pin 退役 —— 挂 18 列车,现在勿动工 #5082 (other lanes) each add one.changeset/<n>-*.mdand grade it by whether pre mode is in; no shared file. Premises re-read on3d9188502e: nopre.json; pending changesets17 : minor,32 : patch, nomajor.Landing: ⛔ not by this seat. The card states "The merge is the maintainer's". On ACCEPT the PR goes to the maintainer as awaiting a human merge. #21988 is ⛔ not merged before this lands.
objectstack-fleet commentedon Oct 7, 2026
os-dev-report
{
"issue": 22080,
"status": "done",
"branch": "claude/issue-22080-v18-pre-mode",
"pr": "#22084",
"session": "session_01VF48aw8RPG6wzDnMgp6rtw (subagent: the dispatching PM's session; the relay derived the same id from CLAUDE_CODE_REMOTE_SESSION_ID)",
"premise_still_valid": true,
"summary": "Draft PR #22084 (head 52f7a50, base main 3d91885) carries both steps: (1) .changeset/pre.json, written by
pnpm changeset pre enter next(@changesets/cli 3.0.3), content exactly {"mode": "pre", "tag": "next"} (v3 writes mode and tag only; commit d3d35a1); (2) .changeset/22080-v18-line-opens.md, front matter\"@objectstack/spec\": major, body = the v18 opening note (ADR-0131; #22050) +Clause-②: no+ the ADR-0087 marker not-required (no-migration-prescription) (commit 52f7a50). Step 2 not skipped: the card's count command on 3d91885 prints 17 : minor, 32 : patch, no major. Member choice: @objectstack/spec, because scripts/sync-protocol-version.mjs derives PROTOCOL_VERSION from that package's major and ADR-0131 C8 calls the line protocol 18. No-major guard reads pre.json from the HEAD checkout, not the base: scripts/check-changeset-no-major.mjs:396 REPO_ROOT = the checkout the script runs in; :2018 readPre(root) reads join(root, '.changeset', 'pre.json') from the working tree; :2098 passes it to judge; :662 returns exempt on pre.mode === 'pre'; CI (pr-automation.yml:1130, Check Changeset) runs it on the PR merge-ref checkout with --base only setting the diff start. Measured: exit 0 exempt (tag: next) as committed; control with pre.json deleted from the working tree only = exit 1 enforce (base has no pre.json, so a base reader could never answer exempt); restored via git checkout HEAD, git diff HEAD empty, exit 0 again. So no split; no deviation of that kind. release.yml path quoted in the PR body: .github/workflows/release.yml:1762 stepPublish to npm + push version tagsrunspnpm run release(:1772) = root package.jsonreleasescript, ending in scripts/release-publish.sh:64changeset publish(no --tag); @changesets/cli 3.0.3 dist/getPublishPlan.mjs:599-603 getReleaseTag returns preState.tag (next) when no --tag and pre state present (except a package whose every published version is already a next prerelease); dist/publish.mjs:61-63 refuses a custom tag in pre mode; npm view today: all 69 fixed-group packages latest=17.7.0, no next tag, so each publishes to next and latest stays 17.7.0. No publish run. Throwaway (detached worktree at 52f7a50, never committed, removed):pnpm changeset versionexit 0, all 69 fixed-group members at 18.0.0-next.0, pre.json unchanged, 37 consumed changesets moved to .changeset/pre/, packages/spec/CHANGELOG.md opens## 18.0.0-next.0/### Major Changes. Card's After-it-lands expectation is FALSE as the files stand: running the remaining three rewriters of the rootversionscript in the same throwaway and replaying release.yml's post-version shape assertion gives 0 unexpected and 4 major-only paths (packages/spec/src/kernel/protocol-version.ts 17 to 18, and blank template objectstack.config.ts, objectstack.manifest.json, package.json), so the version-pr job's stepValidate the post-version tree(release.yml:518) exits 1 at :610-613 and the changesets/action step that would refresh #21988 does not run; cut-rc.yml refuses tagnext(:232-237) and non-rc versions (:156-159). No lane cuts 18.0.0-next.0 without a workflow change outside this card. Flagged in the PR body (risk section + 维护者速读) and in open_questions.","tests": "All on 52f7a50 (final commit; no push after the run), exit codes captured to disk before any pipe. Derived:
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack= 20 commands (15 matched by path, 8 whole-tree), all exit 0;--ranreconciliation:20 derived, 20 run, 0 NOT-MEASURED, 0 UNRUN(a DERIVED zero, all 20 carry exit codes). Card pins:node scripts/check-changeset-no-major.mjs --base origin/mainexit 0✓ Changesets is in pre-release mode (tag: next) ... skipping the no-major guard.; with--eventcarrying the PR body: exit 0,✓ LEVEL AXIS: this PR declares clause-② no;node scripts/check-changeset-fixed.mjsexit 0✓ .changeset/config.json \"fixed\" group is in sync with 69 public workspace packages.node scripts/check-adr-0087-registration.mjs --base origin/mainexit 01 declared-breaking changeset(s), each carrying an ADR-0087 disposition ... not-required (no-migration-prescription); probe (local unpushed commit without the marker) exit 1declares a breaking change (major) but no adr-0087: disposition marker.check-empty-changeset --base origin/mainexit 0; self-tests: adr-0087 441 assertions, no-major 339, empty-changeset 170, check:changeset-gate-self-tests, all exit 0. Also exit 0: check-closing-keyword-parity (+self-test), check-comment-mask-corpus (8323 files, 0 disagree), release-rehearsal-clone --self-test, release-pending-publish --self-test, check:driver-memory-census, check:gitlink-declared, check:nul-bytes (10074 files, no control bytes), check:objectui-changeset, check:pm-changeset-deadline-census, check:published-files, check:refd-timer-probe, check:watch-hint-literal. Beyond derivation, exit 0: check:future-spec-major, check:lockstep-package-count (69), check:docs-image-tag. NOT MEASURED: the 4 type-check lanes (no TypeScript in the diff); no package build/test (diff touches no package). CI on #22084 at report time: Check Changeset, Lint & Repo Gates, Type Check x4, Test Core, Governed Surface Queue Guard in_progress; claim/closing/size/link/dogfood checks success. Not waited on.","gates": {
"derived_commands": 20,
"run": 20,
"exit_nonzero": 0,
"reconciliation": "20 derived, 20 run, 0 NOT-MEASURED, 0 UNRUN",
"extra_run": [
"node scripts/check-changeset-fixed.mjs :: exit 0",
"pnpm check:future-spec-major :: exit 0",
"pnpm check:lockstep-package-count :: exit 0",
"pnpm check:docs-image-tag :: exit 0"
],
"card_pins": {
"check-changeset-no-major (head, --base origin/main)": "exit 0 (pre-release exemption, tag next)",
"check-changeset-no-major (--event with PR body)": "exit 0 (level axis: Clause-② no)",
"check-changeset-fixed": "exit 0",
"pre.json at head": "{"mode": "pre", "tag": "next"}"
},
"ci_at_report": "in_progress"
},
"line_budget": "18 changed lines (+18 / -0) over 2 files, under the 5000 human-merge threshold; no skills/** or governed surface touched",
"files_changed": [
".changeset/pre.json",
".changeset/22080-v18-line-opens.md"
],
"deviations": [
"None of the split kind: the guard reads pre.json from the head checkout, so step 1 and step 2 ship in one PR as the card intends.",
"PM's figure '20 commands with 15 more families once the changeset exists' did not reproduce: the derivation over the actual diff (changeset included) prints 20 commands, of which 15 are matched by path; I ran the 20 plus 4 extras.",
"One local probe commit without the ADR-0087 marker was made to read the gate's verdict, never pushed, and undone with git reset --soft HEAD~1 (my own unpushed commit).",
"Commit trailers are the AGENTS.md model-free pair (Claude-Session + Co-authored-by: Claude) rather than the harness reminder's model-named Co-Authored-By; the PR body footer is the AGENTS.md session-URL form rather than the harness reminder's form.",
"Labels documentation, size/s, tooling on #22084 were set by the repo's labelers, not by this run."
],
"mcp_calls": "0",
"api_writes": "3 — each one relay stroke (POST /repos/objectstack-ai/objectstack/dispatches, executed as objectstack-fleet[bot]): pr_create = POST /repos/objectstack-ai/objectstack/pulls (#22084, draft); label-write assign = POST /repos//issues/22084/assignees (os-justin); post-stamped = POST /repos//issues/22080/comments (this report). Plus 3 git pushes (not REST).",
"rest_writes": "3 — same as api_writes",
"open_questions": [
{
"question": "After #22084 lands, which lane cuts 18.0.0-next.N? release.yml version-pr refuses the major-boundary paths at
Validate the post-version tree(:610-613; measured: protocol-version.ts + 3 blank-template files), so #21988 is not refreshed; cut-rc.yml accepts only tag rc and X.Y.Z-rc.N.","options": [
"A: land #22084 now; a follow-up card (sub-issue of #15194) wires the version-pr lane for the one-time major boundary (the content half already runs check:template-version-sync; add the protocol-version lockstep check, then drop those paths from the major-only refusal), and fixes the release-index re-date below in the same family.",
"B: land #22084 now; extend cut-rc.yml to accept tag next and X.Y.Z-next.N (it already allowlists the major-boundary paths) and cut prereleases by human dispatch.",
"C: hold #22084 until A or B lands."
],
"recommendation": "A. Business need: the ruling and the card name the version PR (#21988) as the route, with publishing as the maintainer's approval; A delivers that route, B invents a second. Long-term: the lane itself names the remedy (
Wire them in before letting this refresh through), and the major boundary is crossed once (at next.0; GA moves no major-only path), so A is a bounded one-time wiring, not a standing exception. AI-error axis: A keeps one release route and its loud shape assertion; B widens an rc-specific lane whose rc wording runs through its summary and dist-tag lines. Startup focus: no new gate family; A reuses gates the lane already runs. C is rejected: the red refresh is the lane's designed refusal, publishes nothing, and holding pre mode back leaves v18's breaking stages graded minor in the meantime. #21988 stays unmerged under all three."}
],
"out_of_scope_findings": [
"class: a · reach: named producer — .github/workflows/release.yml job version-pr (cron 0 */6 * * *), step
Validate the post-version tree(:518), exit 1 at :610-613 on the first refresh after #22084 merges; cut-rc.yml :156-159 and :232-237 refuse tag next · evidence: throwaway at 52f7a50, full rootversionscript (changeset version + sync-protocol-version + sync-template-versions + sync-docs-image-tags + sync-release-index-currency, all exit 0), the step's shape assertion replayed: 0 unexpected paths, MAJOR_ONLY = packages/spec/src/kernel/protocol-version.ts, packages/create-objectstack/src/templates/blank/{objectstack.config.ts,objectstack.manifest.json,package.json}; the changesets/action step has no if: so it does not run after the failure · route: sub-issue of #15194 (falls inside the v18 epic) · dedupe words: version-pr major boundary; Validate the post-version tree; MAJOR_ONLY unvalidated; 18.0.0-next.0 version PR; cut-rc tag next","class: a · reach: named producer — scripts/sync-release-index-currency.mjs, run by the root
versionscript on every lane · evidence: same throwaway rewrote content/docs/releases/index.mdx v17 entrycurrent series: 17.7.0, released 2026-10-06toreleased 2026-10-07(the cut's date); 17.7.0's version commit 4e4e881 is dated 2026-10-06; in pre mode the newest GA of 17 does not move and rewriteStatusField re-dates a same-version entry (its battery B pins that), so every pre-mode cut re-dates the last GA · route: same family as the finding above, fold into that card · dedupe words: release index currency prerelease date; sync-release-index-currency pre mode; current series released date restamp","carrier: the lane-wiring card above · noted, not filed — sync-docs-image-tags moves the 9 docs pins (docker/README.md, content/docs/deployment/self-hosting.mdx, content/docs/upgrading.mdx) from 17.7.0 to 18.0.0-next.0 on the first prerelease, so self-hosting docs on main would name a prerelease while latest is 17.7.0; by the rewriter's design (docs track packages/cli), whether that is wanted during the next line is the lane card's call",
"carrier: none · noted — create-objectstack's committed blank template pins ^18.0.0 after the version pass, which no 18.0.0-next.N satisfies; checked and not a defect: packages/create-objectstack/src/pkg-utils.ts:23 rewrites deps to ^OWN_VERSION at scaffold time"
],
"cleanup": "throwaway worktree: version output discarded (git diff HEAD empty), node_modules removed, git worktree remove without --force; task worktree /home/user/objectstack-issue-22080 is clean and fully pushed, node_modules + worktree removed right after this report posts; no server or background process started"
}
Generated by Claude Code
objectstack-fleet commentedon Oct 7, 2026
os-dev-report
{
"issue": 22080,
"round": "patch round for PR #22084: Lint & Repo Gates red, step PM dispatch-gates self-test",
"status": "blocked",
"branch": "claude/issue-22080-v18-pre-mode",
"pr": "#22084",
"head": "52f7a509c6 (unchanged; no push this round)",
"session": "session_01VF48aw8RPG6wzDnMgp6rtw",
"blocked_on": "The fix is outside .changeset/. It needs the seat to widen the surface to scripts/check-adr-0087-registration.mjs (option A), or to rule on B or C. Per the stop rule nothing was edited or pushed.",
"failing_case": "dispatch-gates self-test case at scripts/pm/dispatch-gates.mjs:19218, verbatim:
✗ the extension narrowing costs no lead — every hint the loose rule resolves, this one resolves too (refused: .changeset/pre); summary✗ dispatch-gates self-test: 1 of 1976 case(s) failed.","reproduction": "Local, at 52f7a50:
pnpm check:pm-dispatch-gatesrun detached, BATTERY-EXIT=1, 1068.8s. The only failing line is the one above, which matches CI job 112831153422.","control": "At origin/main 3d91885, same command: BATTERY-EXIT=0,
✓ dispatch-gates self-test: 1976 cases pass., 1009.7s; the same case reads(refused: none). So the red is this PR's.","reading": "The hint comes from scripts/check-adr-0087-registration.mjs:536
const isConsumedPrerelease = (p) => p.startsWith('.changeset/pre/');. extractWatchHints reads the literal.changeset/pre/, and collapseHint (dispatch-gates.mjs:7367) strips the trailing slash, which gives.changeset/pre. It is owned by check:changeset-gate-self-tests and the three check-adr-0087 invocations. The case's loose rule resolves.changeset/preto.changeset/pre.json, a tracked sibling plus a dot. The strict rule (MODULE_SPECIFIER_EXTENSIONS, :10211, .ts through .jsx) refuses it, so the two rules disagree. A probe that replays the case shows: at head, 988 hints, refused = [.changeset/pre]; at the control, refused = []. The case fails only while pre.json is tracked and.changeset/pre/holds no tracked file. The first cut moves consumed changesets there and clears it, and that cut is itself blocked by the version-lane finding. Merged as is, #22084 would red the required Lint & Repo Gates on main and on every PR until then.","seat_suggested_literal": "Measured, and it is wrong: changing the literal to
.changeset/pre.jsonmakesnode scripts/check-adr-0087-registration.mjs --self-testexit 1 with 2 failures, includingPRE1: the audit surfaces read PENDING stock only -- two consumed changesets under .changeset/pre/ must not appear. The literal names the consumed-changeset DIRECTORY, not the pre state file. The probe was applied with scripts/ablation-replace.mjs and restored with blob == HEAD and git diff HEAD empty.","proposed_change": "Not made in the PR. In scripts/check-adr-0087-registration.mjs:536, replace the one line with two:
const CONSUMED_PRERELEASE_EXCLUDED = '.changeset/pre/';andconst isConsumedPrerelease = (p) => p.startsWith(CONSUMED_PRERELEASE_EXCLUDED);. The literal and the predicate are both unchanged. The literal moves into a top-level declaration whose name matches dispatch-gates' EXCLUSION_DECL_NAME (_EXCLUDED), so the extractor reads it as an excluded surface, which is what it is: the docblock above it (:530-535) and :2097 say the predicate excludes consumed stock from the audit surfaces. The file's hints change from [.changeset, .changeset/pre, .changeset/.md] to [.changeset, .changeset/.md], and.changesetstill covers .changeset/pre/**, so no routing lead is lost. It is not a one-literal change, because the literal's text cannot move without changing what the predicate matches.","watch_hint_literal_covers_it": "No. check:watch-hint-literal rosters only ROOT_DIR_WATCH_HINTS, ROOT_FILE_WATCH_HINTS, ROOT_WATCH_HINTS and DECLARED_WATCH_HINTS (72 declarations), and :536 is none of them. It exits 0 with the change.",
"throwaway_verdict": "Throwaway worktree at 52f7a50 plus local commit 07d3ac4863, never pushed and now removed:
pnpm check:pm-dispatch-gatesBATTERY-EXIT=0,✓ dispatch-gates self-test: 1976 cases pass., 947.5s, and the case reads(refused: none). check-adr-0087 --self-test exits 0 (441 assertions), check-adr-0087 --base origin/main exits 0, and check:watch-hint-literal exits 0. The widened surface derives 41 commands, versus 20 for .changeset/ only. The 20 added commands, other than the battery, were run on the throwaway and all exit 0. NOT MEASURED: the change on main alone, without pre.json.","changeset_only_alternative": "Measured and not adopted: a tracked placeholder
.changeset/pre/.gitkeepmakes.changeset/prea tracked prefix. The probe then refuses nothing, and changesets v3changeset versiontolerates the file (exit 0, fixed group at 18.0.0-next.0). I did not adopt it because it is a decoy file in changesets' managed store whose only purpose is to steer a self-test heuristic, and the case's own comment asks for a decision, not a dodge.","root_cause": "The frozen self-test's loose rule reads a trailing-slash directory literal as an extensionless module specifier. scripts/pm/dispatch-gates.mjs was not edited.",
"open_questions": [
{
"question": "How does the surface widen to clear the battery for #22084?",
"options": [
"A: widen to scripts/check-adr-0087-registration.mjs and land the two-line exclusion-constant change, either in #22084 or in a PR that lands before it",
"B: commit the .changeset/pre/.gitkeep placeholder inside the current surface",
"C: a ruling-208 exception to narrow the self-test's loose rule in dispatch-gates.mjs"
],
"recommendation": "A. It is accurate, because the literal is an exclusion; it is measured green; it is the smallest change; and it touches no frozen file. B leaves a workaround in the release store, and C needs an exception for a file that is frozen."
}
],
"deviations": [
"The dispatch said to run the battery through scripts/pm/os-verify-lock.sh. My definition says check:* batteries do not take the lock and run as nohup plus tail --pid, and the gate's own header says to run detached. I followed the definition and the header: all three batteries ran detached, waited on in the foreground with tail --pid.",
"No push, because the fix is outside .changeset/."
],
"mcp_calls": "0",
"api_writes": "1: this comment, POST /repos//issues/22080/comments through the relay",
"cleanup": "The control, probe, candidate and task worktrees were all removed without --force, after their node_modules. Battery processes were started detached and each has exited. The candidate patch is saved in the scratchpad."
}
Generated by Claude Code
objectstack-fleet commentedon Oct 7, 2026
Surface amendment to claim
6039111470·domain:devx#2·session_01VF48aw8RPG6wzDnMgp6rtw· 2026-10-07T15:20Z. ⛔ Not a new claim; the claim, branch and assignee stand.Why: PR #22084's head
52f7a509c6reds the requiredLint & Repo Gates. The step isPM dispatch-gates self-test, casethe extension narrowing costs no lead … (refused: .changeset/pre). The patch-round addendum6040911886reproduced it. The control on3d9188502eis green, so the red is this PR's..changeset/pre/atscripts/check-adr-0087-registration.mjs:536. With.changeset/pre.jsonnow tracked, the battery's loose and strict hint rules disagree on it.mainand every PR until a first cut lands.Ruled (seat; a technical sequencing call, no product change): option A of the addendum.
.changeset/plusscripts/check-adr-0087-registration.mjs. In that file, only the line at:536becomes a top-levelCONSUMED_PRERELEASE_EXCLUDEDconstant and theisConsumedPrereleasepredicate reading it.EXCLUSION_DECL_NAME(scripts/pm/dispatch-gates.mjs:6415), so the extractor reads it as the excluded surface it is: the audit filter at:2092.mainnever carriespre.jsonwithout it..changeset/pre/.gitkeepplaceholder, a decoy in the changesets store;dispatch-gates.mjs.Serial constraints, re-read: no open PR touches
scripts/check-adr-0087-registration.mjs, and no in-flight claim names it (#15207, #13458, #5082, #15205, #15196, #21898 read). Its last touch onmainis6eaa0f4a81.objectstack-fleet commentedon Oct 7, 2026
os-dev-report
{
"issue": 22080,
"round": "option A applied on PR #22084, under surface amendment 6040954045",
"status": "done",
"branch": "claude/issue-22080-v18-pre-mode",
"pr": "#22084",
"head": "a630de657d. Normal commit on 52f7a50; no amend, no force. Pushed 52f7a50..a630de6.",
"session": "session_01VF48aw8RPG6wzDnMgp6rtw",
"change": "Only line :536 of scripts/check-adr-0087-registration.mjs changed. It is now two lines:
const CONSUMED_PRERELEASE_EXCLUDED = '.changeset/pre/';andconst isConsumedPrerelease = (p) => p.startsWith(CONSUMED_PRERELEASE_EXCLUDED);. The diff is identical to the measured candidate patch, index lines aside. Nothing else in that file moved: 2 insertions, 1 deletion.","ran_line": "Run reconciliation — 41 derived, 41 run, 0 NOT-MEASURED, 0 UNRUN. ✓ dispatch-gates --ran: 41 derived famil(ies) accounted for — 41 run, 0 NOT-MEASURED (a DERIVED zero — all 41 recorded an exit code and none of them is 3).",
"derivation": "
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackat a630de6 gives 41 commands (34 matched by path, 2 by change kind, 8 whole-tree). The list is the same set as the throwaway measurement. All 41 exit 0, and every exit code was written to disk before any pipe.","battery": "
pnpm check:pm-dispatch-gateswas run detached at a630de6. BATTERY-EXIT=0, wall 967s; the battery's own line readsthe battery took 965.7s on this box. Summary:✓ dispatch-gates self-test: 1976 cases pass.","case_reading": "
✓ the extension narrowing costs no lead — every hint the loose rule resolves, this one resolves too (refused: none)","adr_0087": "
--self-testexits 0:✓ check-adr-0087-registration --self-test: 441 assertions over real temp git repos.--base origin/mainexits 0:✓ check-adr-0087-registration: 1 declared-breaking changeset(s), each carrying an ADR-0087 disposition.","card_pins_rechecked": "check-changeset-no-major --base origin/main exits 0 (pre-release exemption, tag next). check-changeset-fixed exits 0 (69 packages in sync). The .changeset/ files are unchanged.",
"ci_at_report": "One read of a630de6: Check Changeset success, Lint & Repo Gates in_progress, 23 success, 7 skipped. I did not wait.",
"pr_body_line_for_the_seat": "For
## 维护者速读(草稿), under 改了什么, append: 另外,scripts/check-adr-0087-registration.mjs里有一行把已有的排除路径.changeset/pre/改写成_EXCLUDED命名常量(匹配逻辑不变),这样pre.json存在后,PM 门禁自检能正确识别它。","pr_body_now_stale": [
"The opening paragraph says
File surface: .changeset/ only.Suggested text:File surface: .changeset/ plus one line in scripts/check-adr-0087-registration.mjs (surface amendment 6040954045 on #22080).","The same 改了什么 paragraph says 改动只有
.changeset/下的两个文件,没有代码、工作流或门禁改动. The appended line above contradicts it. Suggested text: 改动是.changeset/下的两个文件,加上门禁脚本里的一行重命名;没有代码或工作流改动。","The Gates section reports 20 derived commands at 52f7a50. At a630de6 the derivation gives 41 commands, all exit 0, with the
--ranline above."],
"mcp_calls": "0",
"api_writes": "1: this comment, POST /repos//issues/22080/comments through the relay. There was also 1 git push. The PR body was not PATCHed.",
"cleanup": "The task worktree is removed after this comment posts. The battery process has exited. No server was started."
}
Generated by Claude Code
objectstack-fleet commentedon Oct 7, 2026
ACCEPT — PR #22084 ·
domain:devx#2· 2026-10-07T15:46ZSeat review of PR #22084 against GitHub, at head
a630de657don base3d9188502e. Report:6039596838; patch-round addendum:6041313497. Claim:6039111470. ⛔ The landing is not this seat's: the card says "The merge is the maintainer's", so the PR goes to the maintainer as awaiting a human merge.Checklist conclusions
main. Body line 1 isFixes #22080; no other closing keyword in the body.Clause-②: nois at line start.get_files):.changeset/pre.json(+4),.changeset/22080-v18-line-opens.md(+14) andscripts/check-adr-0087-registration.mjs(+2 −1). That is the claim's surface as amended in6040954045. No edit to either changeset guard's logic,.changeset/config.jsonorrelease.yml; nocontent/docs/releases/change.52f7a509c6,Lint & Repo Gateswas red atPM dispatch-gates self-test, case… (refused: .changeset/pre). The cause: withpre.jsontracked, the battery's loose and strict hint rules disagreed on the literal.changeset/pre/atcheck-adr-0087-registration.mjs:536. The control onmainwas green. The fix names the existing exclusionCONSUMED_PRERELEASE_EXCLUDED, soEXCLUSION_DECL_NAME(dispatch-gates.mjs:6415) reads it as excluded. The diff is exactly two lines; the predicate's match is unchanged. Ata630de657d: 41 derived commands, all exit 0; the battery passes 1976 cases, with(refused: none);check-adr-0087-registration --self-testand--base origin/mainexit 0. ⛔ Not taken: a.gitkeepdecoy in the changesets store, or an exception to frozendispatch-gates.mjs.pre.json:{"mode": "pre", "tag": "next"}."@objectstack/spec": majorgrades onefixedmember. The no-major count on the cut was17 : minor,32 : patch, nomajor, so step 2 was owed.PROTOCOL_VERSIONfollows@objectstack/spec's major … reads18.0.0":protocol-version.ts:18holds'17.0.0', andsync-protocol-version.mjs:22derives it from spec's major.lateststays 17.x;@nexton request) match the publish path the PR body quotes.Clause-②: noline follows the pending convention (34 of 37.changeset/*.mdonmaincarry one). Its ADR-0087 marker isnot-required (no-migration-prescription).scripts/check-changeset-no-major.mjson3d9188502e:REPO_ROOTisresolve(__dirname, '..')(:396), the checkout it runs in;readPre(root)reads that tree's.changeset/pre.json(:2018);judgereturnsexemptonmode === 'pre'(:662), wired at:2098.a630de657d: 29 success, 9 skipped (path-filtered: Build Core, the dogfood matrix and Temporal; Check Changeset reruns; the opt-in tarball smoke), 0 red. Every required context is green:Lint & Repo Gates,TypeScript Type Check,Test Core,Dogfood Regression GateandGoverned Surface Queue Guard.The dev's out-of-scope findings and open question
version-prlane refuses the major boundary. The seat re-readrelease.yml:518and:610–:613, andcut-rc.yml:156–:159and:232–:237. Filed release(v18): the version-pr lane refuses the major boundary atValidate the post-version tree, so #21988 never refreshes into 18.0.0-next.0 — wire the lane's major-only gates in, and stop prerelease cuts re-dating the last GA #22085, an in-flight derivative (p1,target:v18). Its PR fix(release): judge the major-boundary template stamps on the version-pr lane, and stop prerelease cuts re-dating the last GA #22095 (Part of) carries the template half and the release-index date fix, and is in the merge queue. The protocol half needs the maintainer's ruling,6040990462on release(v18): the version-pr lane refuses the major boundary atValidate the post-version tree, so #21988 never refreshes into 18.0.0-next.0 — wire the lane's major-only gates in, and stop prerelease cuts re-dating the last GA #22085 (Q1–Q3).Validate the post-version tree, so #21988 never refreshes into 18.0.0-next.0 — wire the lane's major-only gates in, and stop prerelease cuts re-dating the last GA #22085.Validate the post-version tree, so #21988 never refreshes into 18.0.0-next.0 — wire the lane's major-only gates in, and stop prerelease cuts re-dating the last GA #22085.^18.0.0: Acceptance notes. It is not a defect, because the scaffold rewrites dependencies to its own version (pkg-utils.ts:23, the dev's reading).6037890422: "Once the opening lands, changesets/action turns it into the prerelease version PR." The version PR is the ruled route, so release(v18): the version-pr lane refuses the major boundary atValidate the post-version tree, so #21988 never refreshes into 18.0.0-next.0 — wire the lane's major-only gates in, and stop prerelease cuts re-dating the last GA #22085 wires it. B (extendingcut-rc.yml) is not taken. Whether chore(release): enter Changesets pre mode (next) with onemajormarker, so v18 opens at 18.0.0-next.0 #22084 merges before release(v18): the version-pr lane refuses the major boundary atValidate the post-version tree, so #21988 never refreshes into 18.0.0-next.0 — wire the lane's major-only gates in, and stop prerelease cuts re-dating the last GA #22085 lands is the maintainer's choice, since the merge is theirs. Until release(v18): the version-pr lane refuses the major boundary atValidate the post-version tree, so #21988 never refreshes into 18.0.0-next.0 — wire the lane's major-only gates in, and stop prerelease cuts re-dating the last GA #22085's ruling is carried out, each 6-hourlyversion-prrefresh fails atValidate the post-version treeand publishes nothing. ⛔ chore: version packages (next) #21988 stays unmerged either way.Deviations: none that bear on acceptance. The commit trailers are AGENTS.md's model-free pair.
objectstack-fleet commentedon Oct 8, 2026
Ruling pointer: batch #286 item 1 (#22085, the version-lane half of this opening) · Q1 B · Q2 A · Q3 B · maintainer 「22082 22085 同意」 2026-10-08T00:42Z
Director seat, summon #35,
session_01VYToj6PQehTEKNrjGM9akg(via the relay). The record is 6049734955 on #22085, nowpm:queuefor thedomain:devxseat to execute. This card's claim andpm:dispatchedstand. Thread-read: 6041445831.^17→^18, one narrow lockstep exception in pre mode with a pendingmajor), on adomain:speccard the devx seat files; ⛔ not in the version pass./docs/releases/v18before the first prerelease; written by the release side, settled in chat.domain:devxcard.next) with onemajormarker, so v18 opens at 18.0.0-next.0 #22084's merge is the maintainer's act; after it theversion-prrefresh stays red atValidate the post-version treeuntil the Q1 pull request lands, publishing nothing; ⛔ chore: version packages (next) #21988 is not merged.Generated by Claude Code
objectstack-fleet commentedon Oct 8, 2026
Landed — PR #22084 →
a87d8be299·domain:devx#2· 2026-10-08T09:05Zos-zhuang) at 2026-10-08T07:54Z. The squash commita87d8be299is onmain.mainby blob identity: all three files equal the PR heada630de657d:.changeset/pre.jsond20efa9e7d, which reads{"mode": "pre", "tag": "next"};.changeset/22080-v18-line-opens.md91b1263e9b;scripts/check-adr-0087-registration.mjsc961391c80.mainis in Changesets pre mode with the tagnext, and the@objectstack/specmajor marks the v18 line. The next version pass computes18.0.0-next.0.lateststays on 17.7.0.ec8f37c890), the documented image and install pins follow the newest GA in pre mode.Validate the post-version tree, so #21988 never refreshes into 18.0.0-next.0 — wire the lane's major-only gates in, and stop prerelease cuts re-dating the last GA #22085's ruling:release.yml'sversion-prrefresh stays red atValidate the post-version treeuntil spec(v18): move PROTOCOL_VERSION 17 → 18 in an ordinary pull request with full CI: regenerate spec-changes.json and the 17 → 18 upgrade-guide section, rewrite the in-repo ^17 handshakes, and give the lockstep test one pre-mode exception (#22085 Q1) #22130 (the protocol 17 → 18 PR,domain:spec, PR feat(spec)!: PROTOCOL_VERSION 17 → 18 in an ordinary PR — regenerated spec-changes.json and upgrade guide, ^18 handshakes, pre-mode lockstep exception (#22085 Q1 → B) #22215 in review) lands. Red there publishes nothing. The Q2 page is the release side's. ⛔ chore: version packages (next) #21988 is not merged.Fixes #22080(completed).pm:dispatchedis removed in the same act.PROTOCOL_VERSIONfollows@objectstack/spec's major at version time" was written before Q1 was ruled B. The constant now moves in spec(v18): move PROTOCOL_VERSION 17 → 18 in an ordinary pull request with full CI: regenerate spec-changes.json and the 17 → 18 upgrade-guide section, rewrite the in-repo ^17 handshakes, and give the lockstep test one pre-mode exception (#22085 Q1) #22130's ordinary PR, and the outcome is the same (18.0.0). The sentence lands in the18.0.0-next.0CHANGELOG as written. It was told to the maintainer in chat and left as is.chore(release): enter Changesets pre mode (`next`) with one `major` m…
feat(plugin-security,platform-objects)!: a permission-set assignment …