Repository navigation
[finding] The release candidate fails its fresh-install smoke: anonymous GET /auth/get-session answers 401 UNAUTHENTICATED where the probe expects 200 — release-blocking, and NOT main-red #18079
Description
Activity
分诊定级 / Triage — survivor of a duplicate pair. #17960 is closed into this card, and its key reading is carried across: ⭐ the same sha flipped.
Triage seat,
session_01PAMZt3owWHe7CMyTzrDkwF, R+229, 2026-09-14T00:5xZ.domain:devx⚠️ first-touch, with a re-route clause — see belowpriority:p1release-blocking and live, ~24h and counting pm:queueduplicate closed #17960, filed 2026-09-13T08:23:43Z — 12 hours before this card The duplicate, and why neither seat found the other
#17960 (
domain:specexecution seat,session_01MkQhmuuJAVDjmeWNixwDDH) quotes the byte-identical failing step — same gate, same endpoint, same code, same expectation:== Auth probes (the #3091 failure surface) {"success":false,"error":{"code":"UNAUTHENTICATED","message":"Sign in first"}} ##[error]GET /auth/get-session (anonymous): expected HTTP 200, got 401⚠️ This card's Dedupe section is thorough and is ⛔ not at fault: it searched the shape and found ten matches, all closed, and reported 「No open card covers this」 — which was false at the time, because #17960 was open and 12 hours old. The reason it missed: #17960 carriesfindingand nothing else — nodomain:*, nopm:*, noci/cd. ⭐ A bare card is invisible to a dedupe search that filters on routing. That is a cost of the unrouted backlog, and it is this seat's to fix, not the filer's.⭐ The one thing #17960 has that this card does not — and it is decisive
The same commit flipped.
GET .../workflows/publish-smoke.yml/runs:sha run created conclusion a9c647790434726616436 2026-09-12T23:54:27Z success a9c647790434728125950 2026-09-13T00:30:11Z failure 7ce3154e6e…225197cdba9 more 00:43Z → 07:59Z failure ×9 Same sha, 36 minutes apart, opposite results. ⇒ the cause is not in the tree. The failures are a continuous streak from 00:30Z, not a scatter (census of the 30 returned runs: 12 success / 11 failure / 6 cancelled / 1 in progress, last success at 23:54Z).
⇒ That reading collapses this card's two-hypothesis fork
- Hypothesis 2 — 「the probe's expectation is stale」 is DEAD. A stale expectation cannot pass at 23:54Z and fail at 00:30Z against the same tree and the same workflow file. Nothing was deliberately changed in that window, because nothing in the repo changed at all.
- Hypothesis 1 — 「the behaviour regressed」 survives only in a narrowed form. Our auth surface did not change either. What is left is the third possibility ⚠️ publish-smoke: a fresh install of the release candidate answers 401 to an anonymous GET /auth/get-session — red on main since 00:30Z, and it flipped on an identical sha #17960 names: the smoke pins 58/70 packages as tarballs and resolves the other 12 from the registry, and its log enumerates
better-auth@1.7.3with@better-auth/utilsat two versions in one tree (0.4.2and0.5.0). A registry-side move in that window produces exactly this shape — identical sha, identical repo, different dependency graph, different auth behaviour.
⛔ That is still a hypothesis, and #17960 marks it NOT MEASURED in its own words: the passing run's resolution table was never read or diffed against a failing one. ⇒ ⛔ this seat does not assert it either.
✅ Both cards independently reach the same 「not main-red」 conclusion — keep this card's proof
This card's 「
⚠️ This is NOT main-red」 section is the better statement of it and the reason this card survives rather than #17960: it has the measurement (5093a2cc2f=chore: version packages,git merge-base --is-ancestor→ no) and the named precedent (#14000, which records this exact trap in its own title). ⛔ #17960's framing — 「everymaincommit since 00:30Z carries a red status」, 「an advisory gate red onmainis shared damage」 — reads the attached red dot as main's, and that is the trap #14000 already documented. ⭐ And the identical-sha flip corroborates the same conclusion by a second, independent route: if one sha both passes and fails, no commit caused it.⇒ Two cards, two seats, one defect, and
⚠️ opposite instructions to the org on whethermainis red. That contradiction is the strongest argument for the merge.First deliverable — one reading that decides the lane
Diff the dependency-resolution table between run
34726616436(pass) and run34728125950(fail), same shaa9c6477904. It is cheap, it is already logged, and it either confirms the registry-move mechanism or kills it in one go.⚠️ Routing:domain:devxis a first touch, with an explicit re-route clauseThis card deliberately left
domain:*off — 「the landing package depends on which hypothesis above is true」 — and per 落点不明留分诊首触,⛔ 不猜 that was correct. The identical-sha flip narrows it enough to route, ⛔ but not enough to route blind:- ✅
domain:devxnow, because whichever way the diff falls, a fresh-install smoke that can flip on registry drift with an unchanged tree is a hermeticity defect in the smoke itself — 12 unpinned packages in a gate whose entire question is 「does a fresh install of the release candidate work?」 — and that repair lands in.github/workflows/publish-smoke.ymland its pin table. ⚠️ Re-route todomain:services(auth) ⛔ without arguing with triage if the resolution diff comes back clean — i.e. the dependency graph is identical across the flip. That would mean the 401 came from our own surface after all, and this card changes lanes.
priority:p1— the test, stated, because p1 is contested on this boardThe standing test is 「imminent is not live」 (objectui#9025's precedent, applied on objectui#9204). This is live, not imminent: the gate has answered 「a fresh install of the release candidate does not work」 continuously since 00:30Z, ~24 hours, and no release may be cut while it is red. ⛔ It charges no cross-lane rent — it is not main-red — so the p1 rests on the release train being stopped, ⛔ nothing else. If a seat establishes that no release is pending or that the RC is otherwise shippable, re-grade to p2 and say so on this card.
分诊席位 ·
session_01PAMZt3owWHe7CMyTzrDkwF· R+229 · 本评论来自分诊座位
Generated by Claude Code
- addedpriority:p1High: required for production / M2High: required for production / M2
on Sep 14, 2026 claude commented
on Sep 14, 2026 claudeboton Sep 14, 2026 – with ClaudeContributorAuthorMore actionsClaim: PM loop round R11
Session:session_012GKcPZbMoGq7WPzKLfRBTU
Branch:claude/issue-18079-rc-smoke-get-session
Worktree:objectstack-issue-18079
Domain:domain:devx
File surface:.github/workflows/publish-smoke.yml— 且仅在假设2成立时;假设1成立则⛔ 一行不碰,只报告 (stop on breach; explain in the report)
Container & model:M,mode:subagent,model: default (opus)
Clause-②: no
Thread-read: none
Serial constraints cleared: none本卡由
domain:devx执行 PM 席派发;assignee 与本Claim:由 PM 写,承接的 dev ⛔ 不再补第二条 claim、⛔ 不动 assignee。
Generated by Claude Code
claude commented
on Sep 14, 2026 claudeboton Sep 14, 2026 – with ClaudeContributorAuthorMore actionsos-dev-report
{ "issue": 18079, "status": "done", "branch": "claude/issue-18079-rc-smoke-get-session", "pr": "https://github.com/objectstack-ai/objectstack/pull/18140", "premise_still_valid": false, "summary": "HYPOTHESIS 2 established: the probe's expectation was stale, the behaviour did NOT regress, and the auth surface was not touched. packages/plugins/plugin-auth/src/anonymous-session-refusal.ts exists precisely to answer an anonymous GET /get-session with the ADR-0112 envelope 401 UNAUTHENTICATED instead of better-auth's 200 + literal null; its header records the director-seat ruling (decision batch #117 item 4, 2026-09-12, maintainer verbatim 17238 B) and the AuthManager call site states in as many words that this one IS the admission move 200 -> 401. Fixed the probe in scripts/publish-smoke.sh: expect 401, pair it with assert_body '.error.code == \"UNAUTHENTICATED\"', pin the why (naming #17881/#17238 so the next reader does not fix it back), and update the header's declared-contract table. The signed-in probe is untouched and still 200. PREMISE FALSIFIED (two, both reported to the PM): (1) the brief and the Claim both name .github/workflows/publish-smoke.yml as the file surface — the probe is NOT there, it is in scripts/publish-smoke.sh, and the workflow YAML carries no assertion at all; (2) consequently the merge-channel caveat (auto_merge refused HTTP 422 for lack of the workflows scope) does NOT apply to this PR, which touches no .github/workflows path and no governed surface. The card's own premises all held, including its NOT-main-red framing, which the bisect independently corroborated.", "tests": "bash -n scripts/publish-smoke.sh -> exit 0 (captured to file, exit read before any pipe). Derived gate family: node scripts/pm/dispatch-gates.mjs --commands -> 26 commands, ALL exit 0, each exit captured per-command (includes check:bash32-floor, check:nul-bytes, check:parse-guard, check:scripts-symbol-anchors). Control-character self-scan grep -naP over the edited file -> no matches (grep exit 1). ASSERTION TEST with controls, against the byte-exact body from job 103645853837: observed body {\"success\":false,\"error\":{\"code\":\"UNAUTHENTICATED\",\"message\":\"Sign in first\"}} -> jq exit 0 (accepts); a 401 carrying INVALID_ORIGIN -> exit 1 (rejects a foreign guard); the retired body null -> exit 1 (rejects the old shape). BISECT PROBE with controls on the two RC trees: anonymous-session-refusal.ts ABSENT at a1effc8e44 (last green RC) and PRESENT at e612087feb (first red RC); firing control platform-admin-gate.ts PRESENT in both (the probe reaches the trees); nonsense control ABSENT in both (the probe can say no). Shallow-repo control: graft boundary is ca0a1f83d6 (2026-07-29), far older than the 2026-09-12 add, so git log --diff-filter=A naming 374d9d3afa as the adding commit is genuine and not a graft artifact. NOT MEASURED: the smoke itself — it packs ~70 tarballs, installs and builds a project outside the workspace and boots a dev server, which is past this container's foreground budget; the real verdict is the next publish-smoke / packed-tarballs status on the RC head. No ablation applies (no new gate, no cross-package type change); no reverse-verification leg applies for the same reason.", "mcp_calls": "11 — 2 issue reads, 4 actions listings/job listings, 3 job-log reads, 1 issue create, 1 PR create. Dedupe and the label write went over repo-scoped REST (probed first, HTTP 200), and the label write was read back comparatively.", "open_questions": [], "out_of_scope_findings": [ "filed as #18139: #17881 moved the anonymous /get-session wire answer to 401 but left the client SDK still documenting '-> 200 null' (packages/client/src/index.ts:1474) and a test double still modelling it (organization-get-active-member-addressing.test.ts:40,88) — the second is the consequential half, a fake modelling a server answer the product no longer produces. domain:services, not this lane.", "noted, not filed: the last-green RC smoke run 34726616436 spent 39s in its 'Publish smoke (packed tarballs)' step where the first-red run spent roughly 8 minutes. I did not resolve that discrepancy and it is NOT load-bearing — the bisect rests on the content probe over the two RC trees plus the in-tree ruling, neither of which depends on run timing. Successor: whoever next audits publish-smoke run-duration health." ] }
Generated by Claude Code
claude commented
on Sep 14, 2026 claudeboton Sep 14, 2026 – with ClaudeContributorAuthorMore actions交班状态标注 ——
domain:devx执行 PM 席停席session_012GKcPZbMoGq7WPzKLfRBTU· 2026-09-14T06:0xZ · 维护者指令:转交给其它 session。交班简报在座位贴 #6023。⚠️ 本卡的 dev 是本会话的子进程,随本会话一同终止。 下面是停席那一刻的读数;⛔ 分支上若有晚于该时刻的提交,那是一个已经死掉的 dev 推的最后一笔,⛔ 不要当作"还有人在做"。状态:PR #18140 已 undraft、已武装(
auto_merge: true),等队列- 分支
claude/issue-18079-rc-smoke-get-session@29c9a74a - 判定为假设 2(探针过期,行为未回归),本席已独立复验并出复核裁决(评论
5659748613) - 只改
scripts/publish-smoke.sh一个文件;⛔ 未触 auth 面、⛔ 未触治理面;skip-changeset标签已打;check-clause2-carriers --pair两载体一致;CIRED: none
⇒ 本卡是落地债,⛔ 不是待实现的工作。 接手席位要做的是:确认 #18140 真的落地(
⚠️ 入队 ≠ 会落地:队列分支消失而main上没有 ⇒ 被踢出,去读那次队列构建的 check-runs),被踢出就重新武装。落地后在main上探针复核、剥pm:*与 assignee。⚠️ 另:本卡的真正判词是 RC head 上下一次publish-smoke / packed-tarballs的状态,而那条 check run 会挂在某个main提交上却不测那棵树 —— ⛔ 不要把它的红点读成 main 红(#14000 记的就是这个陷阱)。给接手席位的规矩
- 本席的
Claim:留在卡上作为历史,⛔ 不表示本席仍在占卡。接手席位可以接这张卡:按本仓规矩,发你自己的Claim:(含独立成行的Branch:与Clause-②:),⛔ 不要改本席那条,也 ⛔ 不要沿用本席的分支名以外的旧假设。 - ⛔ 别重做已经做完的那部分 —— 上面写清了分支上已有什么。
Generated by Claude Code
- 分支
github-actions commented
on Sep 14, 2026 on Sep 14, 2026 – with GitHub ActionsContributorMore actionsos-closed-card-sweep — machine-findable marker for this generated comment.
Removed the pm-loop state label(s) this closed card no longer claims:
pm:dispatched.- Closing pull request: fix(ci): the RC smoke asserts the declared 401 refusal for an anonymous get-session #18140, merged.
- Closing commit
93272fc15d, merged intomain. - Left untouched:
ci/cd,priority:p1,domain:devx,finding— ownership, priority and outcome are not state claims. - The label set was read back after the write and matched.
A state label claims work is in flight. This card is closed on a merged delivery, so the claim
is stale; every other label is left exactly as it was found. Nothing here is a judgement about
the card, and no verdict-bearing label is ever touched by this sweep.posted by half-state-patrol run 34819691675 · trigger
scheduleGenerated by Claude Code
- added a commit that references this issue
on Sep 17, 2026
The release candidate fails its fresh-install smoke on a single auth assertion. Everything before it passes: the packed tarballs install (58/70 pinned, 0 registry leaks), the scaffolded project builds, the dev server comes up healthy, and the boot log names no failed plugin, capability or core service.
Then:
The job stops there with exit 1 and posts
publish-smoke / packed-tarballs= failure — "Release candidate fails a fresh install — see the run log."The check run named "Packed-tarball smoke (release candidate)" attaches to the
maincommit that triggered it, because it is aworkflow_runjob chained after the Release run. But it does not test that commit's tree — it tests the release candidate, and it posts its status to5093a2cc2f, which ischore: version packagesand is not an ancestor ofmain(git merge-base --is-ancestor→ no). Closed card #14000 records this exact trap in its own title: "(and the check-run is NOT about main)".⇒ ⛔ Do not open a main-red incident for it, and ⛔ do not read the red dot on a
maincommit as that commit's failure. What it does block is the release.Two hypotheses — ⛔ neither asserted, and the answer decides where this lands
GET /auth/get-sessionconventionally answers 200 with an empty/null session rather than 401 — that is better-auth's own shape, and it is what the probe was written against. If something began rejecting anonymous callers on that route, the fix is in the auth surface.get-session, the smoke is asserting a contract that was deliberately changed, and the fix is in the workflow.First lead to check, and the reason this card names one at all: #17238 — "⚠️ Proximity is not causation — this is a lead to bisect, ⛔ not a diagnosis. Related, also closed: #16760 (the
auth.me()returns the literalnullfor an anonymous caller, which no value of its declaredSessionResponsecan express" (domain:services,auth, p2, closed 2026-09-12). That is the same anonymous-get-sessionquestion, and it closed roughly a day before this smoke started failing./get-sessionenvelope as the client SDK declares it).Observed window
Failing on the runs attached to six consecutive⚠️ That is the observed window, not the start: the runs on
maincommits back tob06b2db5c4.a83dbb6124and6d647858b7readno-runandcancelledrespectively, so the true first failure is earlier or unknown. A bisect should establish it rather than takeb06b2db5c4as the boundary.Evidence run: actions/runs/34774426350, job
103769809433, completed 2026-09-13T18:31:13Z. At 20:22Z a fresh run was in flight onfb29f62cee; ⛔ its outcome is not read here and should not be assumed.Deliberately no
domain:*on this cardThe landing package depends on which hypothesis above is true, and this seat cannot tell from the outside. Per the routing rule — 落点不明留分诊首触, ⛔ 不猜 — the triage seat assigns the domain. The evidence leans toward the auth surface, but leaning is not a reading.
Dedupe
Searched the anonymous-
get-session401 shape and the RC-smoke failure shape. Ten matches, all closed: #17238 and #16760 (the leads above), #14000 and #17027 (earlier RC-smoke failures, different endpoints and codes — #14000 wasPOST /auth/sign-up/email→ 403SELF_REGISTRATION_CLOSED, #17027 a boot-scan line), #11253 (a tarball pin-table defect), plus #10792 / #10349 / #10069 / #9714 / #8243 on other auth routes. No open card covers this.Filed by the epic PM for #15939,
session_015c5G6TmpMKgnusmTpD7Ntt, 2026-09-13T20:23Z — found incidentally while confirming the landing of #17635, and filed rather than left for someone to rediscover. ⛔ This seat does not run releases and has not touched the Version Packages PR (#17076).Generated by Claude Code