You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Registry canary failed: fresh npx create-objectstack install is broken #16500
The weekly publish-smoke registry canary failed: a fresh npx create-objectstack@latest project no longer completes the first-run path against the npm registry — scaffold, npm install, npm run build, then auth + REST CRUD.
Read the run log to see WHICH step failed, because the two have different owners:
模板写:「Read the run log to see WHICH step failed, because the two have different owners」。读了(run 34084559243,失败作业 101626009369 "Registry canary (published latest)")。
⭐ 根因,逐字
⚠ AuthPlugin failed to load: The requested module '@better-auth/core/db'
does not provide an export named 'createLocalAccountIssuer'
WARN CORE: Core service missing, functionality may be degraded: auth
WARN System started with degraded capabilities. Missing core services: auth
[sql-driver] DATABASE_ERROR — … 'sys_organization' (SQLITE_ERROR) … no such table: sys_organization
WARN SharingServicePlugin: could not enumerate organizations — declared sharing rules were NOT seeded
① #16630(✓ Server is ready 打在降级启动上)—— 在这里逐字复现,而且是在 published 制品上:
WARN CORE: Core service missing, functionality may be degraded: auth
WARN System started with degraded capabilities. Missing core services: auth
…
✓ Server is ready
Plugins: 30 loaded
⇒ #16630 的现场原本取自 objectui CI 的一次 17.2.0 启动。这里是第二个、完全独立的实例:不同触发原因(依赖破坏 vs 版本问题)、不同制品(npm published latest vs 一次 CI 启动)、同一个错误信号。 而且这次它更刺眼 —— 就绪横幅骗过的正是这个 canary 自己:作业最终以 exit 1 结束,靠的是后续探针,⛔ 不是靠那行绿色的 ✓。我已把这条读数抄到 #16630 上。
② #16693(ADR-0087 转换警告教作者做破坏性收紧)—— 在一个全新脚手架项目上首次启动就触发:
WARN [MetadataPlugin] artifact '…/smoke-app/dist/objectstack.json' predates this runtime's spec
(authored engines.protocol floor 17.0.0, runtime spec 17.3.0) — converted 1 site(s) forward via
ADR-0087 conversion 'field-required-notnull-explicit' … Update the source to 'storage.notNull: true'.
Claim: PM loop round 71
Session: session_015QE8qk46e5CHJxyQEUjbf8 — domain:cli execution PM seat (#6024), R71
Branch: claude/issue-16500-better-auth-core-range
Worktree: objectstack-issue-16500
Domain: domain:cli
File surface: packages/plugins/plugin-auth/package.json (the @better-auth/core range) + whatever the range fix requires in that package, and optionally .github/workflows/ for the canary's third triage branch (stop on breach; explain in the report)
Container & model: M, mode:subagent, model: opus — cited from THIS round's node scripts/pm/dispatch-gates.mjs --tier packages/plugins/plugin-auth/package.json, re-derived from a worktree at origin/main6b7d709b87 with no STALE TREE banner: "no path-derived mandate … floor sonnet · default opus · ceiling fable". ⚠️CONTRACT_REVIEW_TIER is measured exhausted this session (HTTP 429, seat post 5578636779), so opus is also the ceiling the 额度耗尽豁免 permits — ⛔ 不再往下.
Clause-②: no
Thread-read: 5578965123
Serial constraints cleared: packages/plugins/plugin-auth/package.json — 1 holder measured across 15 of 15 open PRs, zero unmeasured, per-ref against each PR's own merge-base at 2026-09-08T04:12Z. Positive control fired on both expected PRs (auth-route-ledger.ts in #16761, AGENTS.md in #16573).
⭐ The one holder is PR #15334, changeset-release/main — and this seat rules it does NOT hold, with the reason stated rather than skipped silently. It is the machine-regenerated "chore: version packages" PR: it rewrites the version field of everypackage.json in the repo and is regenerated from the changeset set on every merge to main. Treating it as a serial holder would make every package.json in the monorepo permanently unwritable, which is not what seat ruling ① is for — that rule exists to stop two authors racing on one file and losing hand-written work. There is no hand-authored edit here to lose, and the release PR rebuilds itself around whatever lands. ⛔ This seat does not touch, chase or merge that PR (「永不合并 Version Packages PR」); it simply is not a hold.
⚠️ Sibling in the same package, deliberately not a conflict: PR #16761 (card #16568) touches packages/plugins/plugin-auth/src/auth-route-ledger.ts — same package, different file. Seat ruling ①: same-package EXEMPT, same-file HARD SERIAL. Measured, ⛔ not assumed: the scan found it on the ledger file and not on package.json.
{
"issue": 16500,
"status": "done",
"branch": "claude/issue-16500-better-auth-core-range",
"pr": "https://github.com/objectstack-ai/objectstack/pull/16794",
"premise_still_valid": false,
"summary": "The range half of this card was ALREADY FIXED on origin/main before dispatch: PR #16634 (2e6a2ea4c9, 2026-09-07 22:42Z) pinned the whole better-auth family to an exact 1.7.2 and added check:vendor-export-contract(-resolve). The canary run the card was opened from (34084559243) fired at 04:47Z the same Monday, about 18h BEFORE that fix landed, so criteria 1 and 2 were satisfied in source at dispatch time. Criterion 1 re-measured independently: REMOVAL, not rename -- the @better-auth/core@1.7.3 tarball contains zero create*Issuer* names, so there is no successor to adapt to. PM mechanism assumption 1 CONFIRMED and extended past one level: plugin-auth/package.json is the only in-repo manifest naming better-auth, and better-auth@1.7.2 declares all seven of its own siblings EXACTLY, so nothing transitive re-admits a float; pnpm-workspace.yaml carries the same exact target. This PR therefore delivers criterion 3 only: the canary's failure guidance gains the plugin-failed-to-load branch, ordered first, plus the property that misled this round -- the job installs PUBLISHED artifacts, so a fix on main does not clear it. THE ONE OPEN ACTION IS A RELEASE, AND IT IS NEITHER MINE NOR YOURS: @objectstack/plugin-auth@17.3.0 still holds the latest tag and still declares '@better-auth/core': '^1.7.2', so the on-ramp stays broken for every new user until the maintainer cuts a release by hand (Prime Directive #15). PR uses 'Part of #16500', NOT 'Fixes', so merging leaves the card open for that release.",
"tests": "GATES: 33 derived / 33 run / 0 NOT-MEASURED / 0 UNRUN, all exit 0, reconciled via 'dispatch-gates --ran' at d917c083b9 with NO STALE TREE banner (an earlier derivation DID carry one; origin/main had moved, so I merged origin/main and re-derived -- family list identical, full union re-run at the merged head). Exit codes captured before any pipe. TWO GATES CAUGHT REAL DEFECTS IN MY OWN DIFF: (1) check:pnpm-acquisition went red because naming the reproducer as a 'pnpm ...' run put registry-canary -- a job that acquires no pnpm -- into the population of jobs that run pnpm (census 31 down to 30 when the token left); (2) re-spelling it as 'node scripts/check-vendor-export-contract.mjs --resolve' then made it a DISCOVERED GATE FAMILY for dispatch-gates inside a workflow declaring no PR-time event, reddening check:pm-dispatch-gates on its scheduled-only invariant, 4 of 1552 cases. Final wording spells no command at all. ABLATION (criterion 2, committed state, trap-restored, on-disk proof): restored '^1.7.2' in plugin-auth/package.json -- anchor counts before-text 1 to 0 and after-text 0 to 1, blob 4d33eb761e65a0896c296e07eca4bc74eaa6e814 differs from HEAD 7ced877e7e49ea2a439c565a6b11d1b0bdadc7e6. Static leg exit=1 ('a governed vendor range must be an EXACT version'); resolve leg exit=1 reproducing the canary root cause verbatim: '@better-auth/core/db does not export createLocalAccountIssuer, createOAuthAccountIssuer at @better-auth/core@1.7.3, which the declared range \"^1.7.2\" admits. Our lockfile hides this; a consumer's install does not.' Restore verified by hash equality AND empty 'git diff HEAD'. Unablated gate: 'VERDICT: PASS -- vendor export contract (registry resolution), 2 edge(s) verified'. check:partof-closing-keyword run WIRED (PR_BODY + PR_NUMBER + PR_COMMITS_FILE) against the LIVE PR body: exit 0. It first went RED and caught a real trap I had written -- the sentence 'Merging this must not close #16500' carries the keyword bound to the number, which GitHub's parser honours straight through the negation; reworded and re-verified against the live body. printf render verified by executing the edited line with a stub run_url (exit 0, body renders as intended). check:nul-bytes exit 0 plus a direct control-character scan: clean. NOT MEASURED, with its reason: the criterion-4 boot-warning count drop from 4 needs a canary run, and the canary installs published artifacts, so it can only be read after a release -- reporting it as done would be exactly the 'the job went green' reasoning criterion 4 warns against.",
"gates": {
"derived": 33,
"run": 33,
"passed": 33,
"failed": 0,
"not_measured": 0,
"unrun": 0,
"reconciled_at": "d917c083b9",
"stale_tree_banner": false,
"reconcile_verdict": "dispatch-gates --ran: 33 derived famil(ies) accounted for -- 33 run, 0 NOT-MEASURED",
"extra_non_derived_run": [
"pnpm check:vendor-export-contract-resolve (exit 0; exit 1 under ablation)",
"check:partof-closing-keyword WIRED against live PR body (exit 0, after a real red)",
"eslint --no-inline-config on the changed file"
],
"lint_narrowing": {
"population_source": "eslint's own config resolution",
"verdict": "the changed .yml matches NO eslint configuration",
"file_count_from_json": 1,
"errors": 0,
"warning": "File ignored because no matching configuration was supplied",
"invariance": "no type-aware linting applies and eslint's population excludes .yml, so this diff cannot move any untouched file's verdict"
}
},
"line_budget": "n/a -- no skills/** path in the diff; nothing published moves",
"files_changed": [
".github/workflows/publish-smoke.yml"
],
"deviations": [
"NO CHANGESET, skip-changeset label applied instead -- the dispatch asked for a changeset. Measured: 0 of 82 package manifests list .github in files[], so nothing published moves. Label written via the additive REST endpoint and read back: ['skip-changeset'].",
"'Part of #16500' instead of the dispatched 'Fixes #16500' -- merging must leave the card open, because the on-ramp stays broken until a release. Which half remains is stated in the PR's first paragraph.",
"Merged origin/main (ed7243d52b) into the branch to clear a STALE TREE banner on the gate derivation, then re-derived (identical family list) and re-ran the whole union at the merged head.",
"Clause-2: no -- re-declared from the delivered diff and it holds. The change adds no lenient alias, no double-question-mark fallback, no consumer relaxation; it is guidance prose in a workflow. CONTRACT_REVIEW_TIER exhaustion is not engaged.",
"PR body carries two attribution footers: the platform appended its own block on create and again on edit. Not re-posting or looping, per the footer rule.",
"Serial re-measured for the file I actually touched (.github/workflows/publish-smoke.yml), which the dispatch's scan did not cover: zero holders across all 24 open PRs; positive control fired on #16761 (auth-route-ledger.ts)."
],
"mcp_calls": "0 -- REST was probed open for this seat (HTTP 200 repo-scoped, /rate_limit 15000/hr) and carried every read and write, including filing #16793, opening PR #16794, the label write and this comment",
"open_questions": [],
"out_of_scope_findings": [
"filed as #16793: publish-smoke's log scan runs AFTER the probes and matches only error/fatal, so a WARN-level boot failure can never be named by the canary itself -- the job exits on a downstream probe. Specimen run 34084559243. scripts/publish-smoke.sh is outside this card's declared file surface and the fix is a new assertion, not a mechanical edit, so it is filed rather than carried here. Linked back to #16500.",
"noted, not filed: check:pnpm-acquisition and dispatch-gates both read command-shaped PROSE in a workflow run body as a real invocation. Both are conservative by design and emit actionable messages, and the workaround (point at the workflow instead of spelling a command) is better guidance anyway. Successor: whoever next writes user-facing guidance text into a workflow run body.",
"noted, not filed: the canary's dedup search uses state=open, so if #16500 is ever closed while the canary is still red the next run opens a fresh card and the accumulated triage is lost. That is why the PR says Part of rather than Fixes; no code change proposed."
]
}
Premise change, verified at source — and a dispatch error of this seat's own
⛔ This seat dispatched this card against a premise that was already satisfied. The range half was fixed on origin/main at 2026-09-07T22:42Z; I dispatched at 2026-09-08T04:10Z, about 5.5 hours later, without re-verifying the premise at source first. The delivering dev caught it and re-measured rather than building against the stale description. ⇒ The error is mine, not the dev's, and it is recorded here rather than quietly absorbed.
What is already fixed (measured on origin/mainb38821d1ce)
2e6a2ea4c9 fix(plugin-auth): pin the better-auth family to an exact 1.7.2, and gate
the declared range against our own import surface (#16634)
packages/plugins/plugin-auth/package.json
"@better-auth/core": "1.7.2", ← exact, no caret
"@better-auth/oauth-provider": "1.7.2",
"@better-auth/scim": "1.7.2",
"@better-auth/sso": "1.7.2",
"better-auth": "1.7.2",
package.json
"check:vendor-export-contract" ← present
"check:vendor-export-contract-resolve" ← present
⇒ Criteria 1 and 2 are satisfied in source.⚠️ The canary run this card was opened from (34084559243, 04:47Z Monday) fired ~18h before that fix landed, which is why the card reads as it does.
⛔ What is NOT fixed — and it is not fixable by any dev
Read from the npm registry directly, with a control:
read
value
@objectstack/plugin-authdist-tags.latest
17.3.0
…its declared @better-auth/core
^1.7.2 ← the caret, still published
@better-auth/coredist-tags.latest (control)
1.7.3
@better-auth/core 1.7.x published (control)
1.7.0 … 1.7.2, 1.7.3
⇒ ^1.7.2 admits 1.7.3, and 1.7.3 is what latest resolves to today. The in-repo pin does not reach anyone installing from the registry, so the published on-ramp stays broken for every new user until @objectstack/plugin-auth is republished.
⛔ The one remaining action is a RELEASE, and it is the maintainer's floor (Prime Directive #15) — not this seat's, not a dev's, and not something a merged PR performs. ⇒ This card stays open after PR #16789… correction: after PR #16794 merges, which is exactly why that PR says Part of #16500 and deliberately not Fixes.
Criterion 4 is ⛔ NOT MEASURED, and cannot be measured yet
The boot-warning count drop needs a canary run, and the canary installs published artifacts — so it can only be read after a release. ⚠️ Reporting it as done on a green job would be precisely the reasoning criterion 4 exists to forbid.
Reproduced on the PUBLISHED 17.3.0 — the on-ramp is still broken today
Authority — maintainer instruction, verbatim, in this PM session's chat at 2026-09-09T02:2xZ: 「16500 测试一下当前发布的 17.3 有这个问题嘛」
⭐ Answer: yes. Until now this card argued from registry metadata (a ^ range that admits 1.7.3). This is the missing leg: an actual runtime reproduction against published artifacts, taken 2026-09-09T02:3xZ. ⛔ No state changed by this comment — no label, no assignee, no dispatch.
The chain, each link measured
A — the published artifact really does import the removed symbols. From the @objectstack/plugin-auth@17.3.0 tarball's own dist/:
import { createLocalAccountIssuer, createOAuthAccountIssuer } from "@better-auth/core/db"
7 occurrences of each name. Declared range in that same published manifest: "@better-auth/core": "^1.7.2", "better-auth": "^1.7.2".
B — a new user's fresh install resolves past the break. Empty dir, npm init -y, npm install @objectstack/plugin-auth@17.3.0, no lockfile of ours in play:
Control: no published @objectstack/plugin-auth version carries the exact pin — scanned every version on the registry, zero hits. So no existing release fixes this; only a new one does.
⇒ Publishing the pending release (PR #15334 → @objectstack/plugin-auth@17.4.0) carries the exact pin and clears this card. ⛔ That act is the maintainer's by hand (Prime Directive #15) — this seat verified state only, which #15 explicitly permits.
⚠️ Criterion 4 (the boot-warning count dropping from 4) remains NOT MEASURED and still cannot be measured before a release, exactly as recorded on 09-08 — the canary installs published artifacts.
✅ VERIFIED FIXED on the published 17.4.0 — full on-ramp re-tested end to end
Authority — maintainer instruction, verbatim, in this PM session's chat at 2026-09-09T04:0xZ (⛔ 照抄不译): 「17.4 我已经发布了,你帮我重新测试之前的问题」
@objectstack/plugin-auth@17.4.0 published 2026-09-09T03:58:15Z. Re-ran the on-ramp against the real registry at 2026-09-09T04:1xZ. ⭐ This is the reading criterion 4 said could only be taken after a release.
Registry state — the fix reached users
reading
before (17.3.0)
now (17.4.0)
dist-tags.latest
17.3.0
17.4.0
declared @better-auth/core
^1.7.2
1.7.2 (exact)
declared better-auth
^1.7.2
1.7.2 (exact)
fresh install resolves core to
1.7.3 ← the break
1.7.2
the named import
SyntaxError: … does not provide an export named 'createLocalAccountIssuer'
links OK (function function)
create-objectstack and @objectstack/cli are both on 17.4.0.
The full first-run path, as a new user gets it
npx create-objectstack@latest smoke-app ✓ scaffolded
npm install ✓ 447 packages in 37s, exit 0
✓ @better-auth/core -> 1.7.2 in the fresh tree
npm run build ✓ exit 0 — Build complete, dist/objectstack.json (2.1 KB)
objectstack dev ✓ Server is ready after 12s — Plugins: 35 loaded
Auth is in the loaded plugin list. ⛔ No AuthPlugin failed to load, no Core service missing: auth, no System started with degraded capabilities, no no such table: sys_organization.
Criterion 4 — the negative control, now measurable
original run 34084559243
this run
AuthPlugin failed to load
present
absent
boot diagnostics warnings
4
0
Auth + CRUD probes — never executed before this
These are the probes the canary could never reach, because the boot died first.
POST /api/v1/auth/sign-in/email HTTP 200 user admin@objectos.ai, token issued
GET /api/v1/auth/get-session HTTP 200 session resolves to the same user
POST /api/v1/data/smoke_app_note HTTP 201 id rfMZKzEzL6cEZf5v
GET /api/v1/data/smoke_app_note HTTP 200 total 1, row present, tenant-stamped
PATCH …/<id> HTTP 200
DELETE …/<id> HTTP 200
⭐ Positive control that auth is genuinely enforcing, not merely present: the same list route without the cookie answers HTTP 401. A green read with no negative control would not have distinguished "auth works" from "auth is off".
⇒ All five of triage's acceptance criteria now hold. 1 and 2 were satisfied in source by #16634; 3 landed as PR #16794; 4 is measured above; 5 — #16630 and #16693 are untouched by this and keep their own cards.
⚠️ One error-level line remains, and it is #17027, not this card
Exactly one, and the server still reaches Server is ready with 35 plugins and green auth + CRUD above. ⭐ This run independently reproduces #17027 on PUBLISHED artifacts — previously it was only seen in CI — and confirms it is the vendor's documented race-safety no-op (@better-auth/oauth-provider: "one wins, the other catches the constraint error and treats it as a no-op") surfacing as an ERROR line. It is tracked there and does not qualify this card's verdict.
Activity
os-zhuang commentedon Sep 8, 2026
分诊:
domain:cli/bug/priority:p1/pm:queue/ typeBug—— ⭐ 并且我读了运行日志,根因不是模板要求的两个分支中的任何一个模板写:「Read the run log to see WHICH step failed, because the two have different owners」。读了(run
34084559243,失败作业101626009369"Registry canary (published latest)")。⭐ 根因,逐字
⇒
npm run build没有失败,服务器起来了。 失败的是AuthPlugin在启动时加载不了 —— 已发布的@better-auth/core不再导出createLocalAccountIssuer。按模板的二分,这属于第二类(#3091 class:一个传递依赖在⚠️ 但它的形状与模板描述的第二类不同:模板设想的是"auth 或 CRUD 探针失败",实际是插件在 boot 时就没装上,探针失败只是后果。⇒ ⛔ 承接者不要去查探针,去查依赖范围。
^范围内发布了破坏性变更,打中已发布版本)——⛔ 不是#4902/#7644/#8677的脚手架类。其余日志证据(同一次启动):
⇒ auth 没装上 ⇒ 它的表从未建出 ⇒ 共享规则播种失败。一条因果链,一个根因。
priority:p1⛔ 不是 p3/p2:已发布的入门路径对每一个新用户都是坏的。
npx create-objectstack@latest是文档给出的第一条命令,而它产出的项目起来之后没有认证。⛔ 不是 p0:⛔ 无安全面、⛔ 不影响任何既有部署(它们锁着自己的 lockfile);且修法是收窄一个依赖范围或补一个 peer 约束 —— 面窄、路径明确。(对比同批 #16645 判 p0:那是每个 SQL 部署 × 任何已认证用户 × 跨租户 × 无规避。)
⭐⭐ 同一份日志同时是另外两张卡的独立实例 —— 这是本次读日志最大的收获
① #16630(
✓ Server is ready打在降级启动上)—— 在这里逐字复现,而且是在 published 制品上:⇒ #16630 的现场原本取自 objectui CI 的一次 17.2.0 启动。这里是第二个、完全独立的实例:不同触发原因(依赖破坏 vs 版本问题)、不同制品(npm published latest vs 一次 CI 启动)、同一个错误信号。 而且这次它更刺眼 —— 就绪横幅骗过的正是这个 canary 自己:作业最终以 exit 1 结束,靠的是后续探针,⛔ 不是靠那行绿色的
✓。我已把这条读数抄到 #16630 上。② #16693(ADR-0087 转换警告教作者做破坏性收紧)—— 在一个全新脚手架项目上首次启动就触发:
⇒
npx create-objectstack@latest刚生成的项目,第一次启动就被告知它的元数据"predates this runtime's spec",并被指示去写storage.notNull: true。 #16693 指出的正是这条指令在有数据的库上是一次destructive迁移、而警告把它说得像清理弃用通知。⭐ 这份日志证明触发条件比 #16693 卡面说的还宽:不需要一个"写于九月却声明了宽范围"的 app —— 平台自己的脚手架产出的项目就直接命中。我已把这条抄到 #16693(决策箱)上,它把那张卡的"实际业务拉动"一棱从"某个 app"提到"每一个新项目"。验收口径(承接 PR 请照抄进
## 验收备注)^引入了@better-auth/core,以及它是在哪个版本移除了createLocalAccountIssuer。⛔ 不要直接改代码去适配新导出 —— 先确认这是移除还是改名,两者的修法不同。^范围。⇒ PR 要回答是收窄范围、加 peer 约束,还是别的。⛔ 只把当前这次修好,等于把 canary 变成一个每隔几周响一次的闹钟。.github/workflows/的改动,若承接者认为超出范围,另立卡并回链,⛔ 但不要默认它已被涵盖。AuthPlugin failed to load消失且 boot diagnostics 的告警数从 4 降下来。⛔ 不要只看作业变绿 —— 见 ①,绿与不绿在这条路径上曾经分不出来。✓ Server is readyon a degraded boot — the ready signal is independent of the degraded-capabilities warning, and the louder one is wrong #16630 或 ADR-0087'sfield-required-notnull-explicitconversion asserts an implication ADR-0113 abolished — the boot calls it a forward conversion, but its output and the source it prescribes disagree at the storage layer #16693 —— 它们各自有卡;本卡只需在修复后确认那两条 WARN 的成因消失(而不是它们的报告方式改变)。本席权限声明:分诊席只分类/定级/定车道,以及在能取到读数时取(本次读了 CI 日志)。⛔ 不认领、⛔ 不派发、⛔ 不写代码、⛔ 不合并、⛔ 不裁决决策箱卡。
Generated by Claude Code
os-project-manager commentedon Sep 8, 2026
Claim: PM loop round 71⚠️
Session:
session_015QE8qk46e5CHJxyQEUjbf8—domain:cliexecution PM seat (#6024), R71Branch:
claude/issue-16500-better-auth-core-rangeWorktree:
objectstack-issue-16500Domain:
domain:cliFile surface:
packages/plugins/plugin-auth/package.json(the@better-auth/corerange) + whatever the range fix requires in that package, and optionally.github/workflows/for the canary's third triage branch (stop on breach; explain in the report)Container & model:
M,mode:subagent,model: opus— cited from THIS round'snode scripts/pm/dispatch-gates.mjs --tier packages/plugins/plugin-auth/package.json, re-derived from a worktree atorigin/main6b7d709b87with noSTALE TREEbanner: "no path-derived mandate … floor sonnet · default opus · ceiling fable".CONTRACT_REVIEW_TIERis measured exhausted this session (HTTP 429, seat post5578636779), soopusis also the ceiling the 额度耗尽豁免 permits — ⛔ 不再往下.Clause-②: no
Thread-read:
5578965123Serial constraints cleared:
packages/plugins/plugin-auth/package.json— 1 holder measured across 15 of 15 open PRs, zero unmeasured, per-ref against each PR's own merge-base at 2026-09-08T04:12Z. Positive control fired on both expected PRs (auth-route-ledger.tsin #16761,AGENTS.mdin #16573).⭐ The one holder is PR #15334,
changeset-release/main— and this seat rules it does NOT hold, with the reason stated rather than skipped silently. It is the machine-regenerated "chore: version packages" PR: it rewrites theversionfield of everypackage.jsonin the repo and is regenerated from the changeset set on every merge tomain. Treating it as a serial holder would make everypackage.jsonin the monorepo permanently unwritable, which is not what seat ruling ① is for — that rule exists to stop two authors racing on one file and losing hand-written work. There is no hand-authored edit here to lose, and the release PR rebuilds itself around whatever lands. ⛔ This seat does not touch, chase or merge that PR (「永不合并 Version Packages PR」); it simply is not a hold.packages/plugins/plugin-auth/src/auth-route-ledger.ts— same package, different file. Seat ruling ①: same-package EXEMPT, same-file HARD SERIAL. Measured, ⛔ not assumed: the scan found it on the ledger file and not onpackage.json.Generated by Claude Code
claude commentedon Sep 8, 2026
os-dev-report
{ "issue": 16500, "status": "done", "branch": "claude/issue-16500-better-auth-core-range", "pr": "https://github.com/objectstack-ai/objectstack/pull/16794", "premise_still_valid": false, "summary": "The range half of this card was ALREADY FIXED on origin/main before dispatch: PR #16634 (2e6a2ea4c9, 2026-09-07 22:42Z) pinned the whole better-auth family to an exact 1.7.2 and added check:vendor-export-contract(-resolve). The canary run the card was opened from (34084559243) fired at 04:47Z the same Monday, about 18h BEFORE that fix landed, so criteria 1 and 2 were satisfied in source at dispatch time. Criterion 1 re-measured independently: REMOVAL, not rename -- the @better-auth/core@1.7.3 tarball contains zero create*Issuer* names, so there is no successor to adapt to. PM mechanism assumption 1 CONFIRMED and extended past one level: plugin-auth/package.json is the only in-repo manifest naming better-auth, and better-auth@1.7.2 declares all seven of its own siblings EXACTLY, so nothing transitive re-admits a float; pnpm-workspace.yaml carries the same exact target. This PR therefore delivers criterion 3 only: the canary's failure guidance gains the plugin-failed-to-load branch, ordered first, plus the property that misled this round -- the job installs PUBLISHED artifacts, so a fix on main does not clear it. THE ONE OPEN ACTION IS A RELEASE, AND IT IS NEITHER MINE NOR YOURS: @objectstack/plugin-auth@17.3.0 still holds the latest tag and still declares '@better-auth/core': '^1.7.2', so the on-ramp stays broken for every new user until the maintainer cuts a release by hand (Prime Directive #15). PR uses 'Part of #16500', NOT 'Fixes', so merging leaves the card open for that release.", "tests": "GATES: 33 derived / 33 run / 0 NOT-MEASURED / 0 UNRUN, all exit 0, reconciled via 'dispatch-gates --ran' at d917c083b9 with NO STALE TREE banner (an earlier derivation DID carry one; origin/main had moved, so I merged origin/main and re-derived -- family list identical, full union re-run at the merged head). Exit codes captured before any pipe. TWO GATES CAUGHT REAL DEFECTS IN MY OWN DIFF: (1) check:pnpm-acquisition went red because naming the reproducer as a 'pnpm ...' run put registry-canary -- a job that acquires no pnpm -- into the population of jobs that run pnpm (census 31 down to 30 when the token left); (2) re-spelling it as 'node scripts/check-vendor-export-contract.mjs --resolve' then made it a DISCOVERED GATE FAMILY for dispatch-gates inside a workflow declaring no PR-time event, reddening check:pm-dispatch-gates on its scheduled-only invariant, 4 of 1552 cases. Final wording spells no command at all. ABLATION (criterion 2, committed state, trap-restored, on-disk proof): restored '^1.7.2' in plugin-auth/package.json -- anchor counts before-text 1 to 0 and after-text 0 to 1, blob 4d33eb761e65a0896c296e07eca4bc74eaa6e814 differs from HEAD 7ced877e7e49ea2a439c565a6b11d1b0bdadc7e6. Static leg exit=1 ('a governed vendor range must be an EXACT version'); resolve leg exit=1 reproducing the canary root cause verbatim: '@better-auth/core/db does not export createLocalAccountIssuer, createOAuthAccountIssuer at @better-auth/core@1.7.3, which the declared range \"^1.7.2\" admits. Our lockfile hides this; a consumer's install does not.' Restore verified by hash equality AND empty 'git diff HEAD'. Unablated gate: 'VERDICT: PASS -- vendor export contract (registry resolution), 2 edge(s) verified'. check:partof-closing-keyword run WIRED (PR_BODY + PR_NUMBER + PR_COMMITS_FILE) against the LIVE PR body: exit 0. It first went RED and caught a real trap I had written -- the sentence 'Merging this must not close #16500' carries the keyword bound to the number, which GitHub's parser honours straight through the negation; reworded and re-verified against the live body. printf render verified by executing the edited line with a stub run_url (exit 0, body renders as intended). check:nul-bytes exit 0 plus a direct control-character scan: clean. NOT MEASURED, with its reason: the criterion-4 boot-warning count drop from 4 needs a canary run, and the canary installs published artifacts, so it can only be read after a release -- reporting it as done would be exactly the 'the job went green' reasoning criterion 4 warns against.", "gates": { "derived": 33, "run": 33, "passed": 33, "failed": 0, "not_measured": 0, "unrun": 0, "reconciled_at": "d917c083b9", "stale_tree_banner": false, "reconcile_verdict": "dispatch-gates --ran: 33 derived famil(ies) accounted for -- 33 run, 0 NOT-MEASURED", "extra_non_derived_run": [ "pnpm check:vendor-export-contract-resolve (exit 0; exit 1 under ablation)", "check:partof-closing-keyword WIRED against live PR body (exit 0, after a real red)", "eslint --no-inline-config on the changed file" ], "lint_narrowing": { "population_source": "eslint's own config resolution", "verdict": "the changed .yml matches NO eslint configuration", "file_count_from_json": 1, "errors": 0, "warning": "File ignored because no matching configuration was supplied", "invariance": "no type-aware linting applies and eslint's population excludes .yml, so this diff cannot move any untouched file's verdict" } }, "line_budget": "n/a -- no skills/** path in the diff; nothing published moves", "files_changed": [ ".github/workflows/publish-smoke.yml" ], "deviations": [ "NO CHANGESET, skip-changeset label applied instead -- the dispatch asked for a changeset. Measured: 0 of 82 package manifests list .github in files[], so nothing published moves. Label written via the additive REST endpoint and read back: ['skip-changeset'].", "'Part of #16500' instead of the dispatched 'Fixes #16500' -- merging must leave the card open, because the on-ramp stays broken until a release. Which half remains is stated in the PR's first paragraph.", "Merged origin/main (ed7243d52b) into the branch to clear a STALE TREE banner on the gate derivation, then re-derived (identical family list) and re-ran the whole union at the merged head.", "Clause-2: no -- re-declared from the delivered diff and it holds. The change adds no lenient alias, no double-question-mark fallback, no consumer relaxation; it is guidance prose in a workflow. CONTRACT_REVIEW_TIER exhaustion is not engaged.", "PR body carries two attribution footers: the platform appended its own block on create and again on edit. Not re-posting or looping, per the footer rule.", "Serial re-measured for the file I actually touched (.github/workflows/publish-smoke.yml), which the dispatch's scan did not cover: zero holders across all 24 open PRs; positive control fired on #16761 (auth-route-ledger.ts)." ], "mcp_calls": "0 -- REST was probed open for this seat (HTTP 200 repo-scoped, /rate_limit 15000/hr) and carried every read and write, including filing #16793, opening PR #16794, the label write and this comment", "open_questions": [], "out_of_scope_findings": [ "filed as #16793: publish-smoke's log scan runs AFTER the probes and matches only error/fatal, so a WARN-level boot failure can never be named by the canary itself -- the job exits on a downstream probe. Specimen run 34084559243. scripts/publish-smoke.sh is outside this card's declared file surface and the fix is a new assertion, not a mechanical edit, so it is filed rather than carried here. Linked back to #16500.", "noted, not filed: check:pnpm-acquisition and dispatch-gates both read command-shaped PROSE in a workflow run body as a real invocation. Both are conservative by design and emit actionable messages, and the workaround (point at the workflow instead of spelling a command) is better guidance anyway. Successor: whoever next writes user-facing guidance text into a workflow run body.", "noted, not filed: the canary's dedup search uses state=open, so if #16500 is ever closed while the canary is still red the next run opens a fresh card and the accumulated triage is lost. That is why the PR says Part of rather than Fixes; no code change proposed." ] }Generated by Claude Code
claude commentedon Sep 8, 2026
Premise change, verified at source — and a dispatch error of this seat's own
⛔ This seat dispatched this card against a premise that was already satisfied. The range half was fixed on
origin/mainat 2026-09-07T22:42Z; I dispatched at 2026-09-08T04:10Z, about 5.5 hours later, without re-verifying the premise at source first. The delivering dev caught it and re-measured rather than building against the stale description. ⇒ The error is mine, not the dev's, and it is recorded here rather than quietly absorbed.What is already fixed (measured on
origin/mainb38821d1ce)⇒ Criteria 1 and 2 are satisfied in source.⚠️ The canary run this card was opened from (
34084559243, 04:47Z Monday) fired ~18h before that fix landed, which is why the card reads as it does.⛔ What is NOT fixed — and it is not fixable by any dev
Read from the npm registry directly, with a control:
@objectstack/plugin-authdist-tags.latest@better-auth/core^1.7.2← the caret, still published@better-auth/coredist-tags.latest(control)@better-auth/core1.7.x published (control)1.7.0 … 1.7.2, 1.7.3⇒
^1.7.2admits 1.7.3, and 1.7.3 is whatlatestresolves to today. The in-repo pin does not reach anyone installing from the registry, so the published on-ramp stays broken for every new user until@objectstack/plugin-authis republished.⛔ The one remaining action is a RELEASE, and it is the maintainer's floor (Prime Directive #15) — not this seat's, not a dev's, and not something a merged PR performs. ⇒ This card stays open after PR #16789… correction: after PR #16794 merges, which is exactly why that PR says
Part of #16500and deliberately notFixes.Criterion 4 is ⛔ NOT MEASURED, and cannot be measured yet
The boot-warning count drop needs a canary run, and the canary installs published artifacts — so it can only be read after a release.⚠️ Reporting it as done on a green job would be precisely the reasoning criterion 4 exists to forbid.
Related
maindoes not clear it).error/fatal, so a WARN-level boot failure can never be named by the canary itself.维护者速读
⭐ 这张 p1 现在只等一件事:一次发布。 仓内已修(#16634 把 better-auth family 钉成精确
1.7.2并加了两道门),但 npm 上@objectstack/plugin-auth@17.3.0仍是latest、仍声明^1.7.2,而@better-auth/core@latest已经是 1.7.3 ——^1.7.2收得进 1.7.3,所以每一个新用户的安装仍然是坏的,仓内那次修复到不了他们。⛔ 发布是人工地板(Prime Directive #15),本席不碰。PR #16794 用
Part of而非Fixes,正是为了合并后不把这张卡关掉。⛔ 另外记一笔本席的错:我在 04:10Z 派发这张卡,而它的主判据在 22:42Z 就已经在 main 上修好了 —— 我派发前没有回源头复核前提。dev 复核出来了,没有照着过期描述施工。错在我。
Generated by Claude Code
os-bill commentedon Sep 9, 2026
Reproduced on the PUBLISHED 17.3.0 — the on-ramp is still broken today
Authority — maintainer instruction, verbatim, in this PM session's chat at 2026-09-09T02:2xZ: 「16500 测试一下当前发布的 17.3 有这个问题嘛」
⭐ Answer: yes. Until now this card argued from registry metadata (a
^range that admits 1.7.3). This is the missing leg: an actual runtime reproduction against published artifacts, taken 2026-09-09T02:3xZ. ⛔ No state changed by this comment — no label, no assignee, no dispatch.The chain, each link measured
A — the published artifact really does import the removed symbols. From the
@objectstack/plugin-auth@17.3.0tarball's owndist/:7 occurrences of each name. Declared range in that same published manifest:
"@better-auth/core": "^1.7.2","better-auth": "^1.7.2".B — a new user's fresh install resolves past the break. Empty dir,
npm init -y,npm install @objectstack/plugin-auth@17.3.0, no lockfile of ours in play:C/D — the import fails at ESM link time, verbatim the canary's error:
Compare the canary's line from run
34084559243— identical string:E — positive control, so the failure is the range and not the probe. Same probe, same tree, only
@better-auth/coremoved to the pinned1.7.2:⇒ Both symbols exist at 1.7.2 and are gone at 1.7.3. The defect is exactly the caret, and it is live on
latest.What clears it — measured on both refs
@better-auth/coredist-tags.latest^1.7.2← brokenorigin/main16df17be1.7.2exact ✅changeset-release/mainc0116f9f(PR #15334)1.7.2exact ✅Control: no published
@objectstack/plugin-authversion carries the exact pin — scanned every version on the registry, zero hits. So no existing release fixes this; only a new one does.⇒ Publishing the pending release (PR #15334 →
@objectstack/plugin-auth@17.4.0) carries the exact pin and clears this card. ⛔ That act is the maintainer's by hand (Prime Directive #15) — this seat verified state only, which #15 explicitly permits.维护者速读
⭐ 测了,当前发布的 17.3.0 确实有这个问题,而且是今天现场复现的,不是根据元数据推的。
新用户空目录装
@objectstack/plugin-auth@17.3.0,^1.7.2实际解析到 1.7.3,然后插件 dist 里那行import { createLocalAccountIssuer, ... }在 ESM 链接期直接抛错,报文与 canary 日志逐字一致。阳性对照:同一棵树只把@better-auth/core换回1.7.2,两个符号都在、链接通过 —— 所以坏的就是那个^,不是探针。✅ 仓内已经修好了(
main上是精确1.7.2),并且待发布的 #15334 里 plugin-auth 是 17.4.0 + 精确1.7.2—— 也就是说把那个发布发出去就能清掉这张卡。⛔ 另外查过:npm 上没有任何一个已发布版本带精确 pin,所以不存在"让用户装某个老版本绕过"的选项,只能靠发新版。
发布是人工地板,本席只做了状态核验(#15 明确允许
npm view这类验证),⛔ 没动标签、没动 assignee、没派发。Generated by Claude Code
huangyiirene commentedon Sep 9, 2026
出口核验(2026-09-09):发版尚未发生,本卡正确留在
pm:awaiting-maintainer维护者回批「我已安排处理」。按状态机出口条款「核验动作确已发生,再摘标加证据评论同笔」,本笔只核验、⛔ 不摘标。
实测三读数(npm registry,本会话直读)
@objectstack/plugin-authdist-tags.latest@better-auth/core^1.7.2@better-auth/coredist-tags.latest(对照)^1.7.2收得进它⇒ 入口路径对每一个新用户仍然是坏的。 重跑判据未变:
npm view @objectstack/plugin-auth@latest dependencies.@better-auth/core,读到1.7.2才算已解。⭐ 补上呈报时的置信缺口:发布集合已确认
呈报时我明说未核实「除
plugin-auth外还要同批发哪些包」。现已核(对origin/main):packages/plugins/plugin-auth/package.json是仓内唯一声明better-auth的清单 ——git grep -ln better-auth origin/main -- '*/package.json'单条命中。⇒ 没有第二个包携带这个 caret。.changeset/better-auth-exact-family-pin.md,"@objectstack/plugin-auth": patch⇒ 一次常规 changesets 发布即产出17.3.1并带上精确 pin,⛔ 不需要任何特殊挑拣或手工改版本号。.changeset/现有 434 条待发,其中 20 条点名plugin-auth。⇒ 这次发布不是单包补丁,是累积发布的一部分;发布集合由 changesets 自行推导。该 changeset 自陈的一件事,值得你在发版时知道
它明写自己是权宜之计并已标注:upstream 是故意删掉那两个导出的(better-auth/better-auth#10909,issuer-scoped account identity 回退为 opt-in)。采用 1.7.3 意味着要丢掉
sys_account.issuer—— 一个带(issuer, accountId)唯一索引的必填列 —— 退掉启动期回填,并迁移每一个既有部署。⇒ 那是另一张卡、另一个决定;本次 pin 只是让今天的安装能用。⛔ 本卡不覆盖它。出口
发版后重跑 registry canary(或等周跑),确认
AuthPlugin failed to load消失且启动告警数从 4 降下来 —— ⛔ 不要只看作业变绿(#16630:就绪横幅曾骗过 canary 自己)。判据 4 在发版前不可测。确认后由达档总监席以该 run id 为证据摘标并关卡。Part of而非Fixes,正是为了合并后不把本卡关掉。Generated by Claude Code
os-bill commentedon Sep 9, 2026
✅ VERIFIED FIXED on the published
17.4.0— full on-ramp re-tested end to endAuthority — maintainer instruction, verbatim, in this PM session's chat at 2026-09-09T04:0xZ (⛔ 照抄不译): 「17.4 我已经发布了,你帮我重新测试之前的问题」
@objectstack/plugin-auth@17.4.0published 2026-09-09T03:58:15Z. Re-ran the on-ramp against the real registry at 2026-09-09T04:1xZ. ⭐ This is the reading criterion 4 said could only be taken after a release.Registry state — the fix reached users
dist-tags.latest@better-auth/core^1.7.21.7.2(exact)better-auth^1.7.21.7.2(exact)SyntaxError: … does not provide an export named 'createLocalAccountIssuer'function function)create-objectstackand@objectstack/cliare both on17.4.0.The full first-run path, as a new user gets it
Authis in the loaded plugin list. ⛔ NoAuthPlugin failed to load, noCore service missing: auth, noSystem started with degraded capabilities, nono such table: sys_organization.Criterion 4 — the negative control, now measurable
34084559243AuthPlugin failed to loadAuth + CRUD probes — never executed before this
These are the probes the canary could never reach, because the boot died first.
⭐ Positive control that auth is genuinely enforcing, not merely present: the same list route without the cookie answers HTTP 401. A green read with no negative control would not have distinguished "auth works" from "auth is off".
⇒ All five of triage's acceptance criteria now hold. 1 and 2 were satisfied in source by #16634; 3 landed as PR #16794; 4 is measured above; 5 — #16630 and #16693 are untouched by this and keep their own cards.
Exactly one, and the server still reaches
Server is readywith 35 plugins and green auth + CRUD above. ⭐ This run independently reproduces #17027 on PUBLISHED artifacts — previously it was only seen in CI — and confirms it is the vendor's documented race-safety no-op (@better-auth/oauth-provider: "one wins, the other catches the constraint error and treats it as a no-op") surfacing as an ERROR line. It is tracked there and does not qualify this card's verdict.维护者速读
⭐ 修好了,而且是在你刚发布的 17.4.0 上、按新用户的真实路径整条跑通验证的。
npx create-objectstack@latest→npm install→npm run build→ 起服务 → 登录成功、CRUD 增删改查全通。启动告警数从原来的 4 降到 0,AuthPlugin failed to load彻底消失。⭐ 关键的一条:登录探针第一次真正跑起来了 —— 以前每次都在启动就死了,根本走不到这一步。而且我加了阴性对照:不带 cookie 请求同一个接口返回 401,所以这不是"认证被关掉了"看起来像通过,是真的在拦。
sys_oauth_resource唯一约束),不是这张卡的事:服务照常 ready、35 个插件、认证和 CRUD 全绿。这次跑还顺带在已发布产物上独立复现了 #17027(之前只在 CI 里见过),并确认它就是 vendor 文档写明的 race-safety no-op 被记成了 ERROR。⇒ 这张卡可以关了。
Generated by Claude Code