Repository navigation
finding(ci): the live-e2e lane's OTHER pin — OBJECTSTACK_REF — states a MUST that nothing can check, and it fails silently in the same way objectui#7689 did #7964
Description
Activity
- addedbugSomething isn't workingSomething isn't workingdomain:devxobjectui devx stream: fix lands on .github/, scripts/ or release pipeline — devx lane cross-repoobjectui devx stream: fix lands on .github/, scripts/ or release pipeline — devx lane cross-repo
on Sep 6, 2026 分诊:
domain:devx/bug+tooling+finding/needs-user-decision/priority:p2⛔
needs-user-decision不与pm:*并存。⚠️ 一处更正,而且它把本卡从「一个未被检查的 pin」变成「两个未被检查的 pin,且它们今天就是错的一对」卡片的表格写:
pin who checks it OBJECTSTACK_VERSIONscripts/__tests__/ci-cd-pipeline-doc.test.ts, as of objectui#7689本席实读
origin/main:$ git grep -n "OBJECTSTACK_VERSION\|OBJECTSTACK_REF" -- scripts/__tests__/ci-cd-pipeline-doc.test.ts (零命中) $ git show origin/main:scripts/__tests__/ci-cd-pipeline-doc.test.ts | grep -c "it(" ← 控制 36⇒ 控制活着(该文件有 36 个
it(块),⇒ 零是读数。objectui#7689 的 PR 尚未合并,因此版本那一半今天也没有任何东西在检查——包括卡片说它已加上的「40 字符全长 object name」形状断言。⇒ 这是本 lane 反复记录的「把分支上的事实写成树上的事实」,本会话第 15 例。
⭐ 而后果比卡片写的更重:那一对今天就是错的
e2e/live/ci/backend.env:11-13 # OBJECTSTACK_REF — … Always the commit the release tag # `@objectstack/cli@${OBJECTSTACK_VERSION}` points at, so the app source and … e2e/live/ci/backend.env:16 OBJECTSTACK_VERSION=17.0.0-rc.2 e2e/live/ci/backend.env:17 OBJECTSTACK_REF=89d2a4eb3f3b6b8f8c0fbc4cb3953cbe8218dc66 pnpm-lock.yaml @objectstack/spec@17.2.0⇒ backend.env 钉在
17.0.0-rc.2,而本仓 lockfile 解析到17.2.0。 卡片自己描述的那个「matched pair of the wrong release」仍然在 main 上,且没有任何东西会说出来——因为修它的那个 PR 还没落地。⭐ 而卡片对危害的刻画本席逐字背书,且它现在是当下事实而非假设:
start-backend.shsparse-checksexamples/app-showcaseout of objectstack-ai/objectstack atOBJECTSTACK_REF, then installs published@objectstack/*atOBJECTSTACK_VERSIONand runs the app metadata from the first against the packages from the second … reproduces exactly the condition the file's own header calls proving nothing.⇒ live-e2e lane 今天在证明什么,是不确定的。
为什么定 p2
-
两个 pin 都没有检查,且它们当前的值与本仓的 lockfile 不一致 ⇒ 那条 lane 的绿色不构成任何关于本仓当前依赖的证据。
-
⭐ 失败模式是静默的,而且比它的前任更难被人眼发现。 卡片说得最准:
the two numbers no longer even look different, because one is a version and the other is a sha. A reader cannot spot this drift by eye the way
17.0.0-rc.2next to17.2.0could eventually be spotted by a human census.⇒ 又是本 lane 一整天在追的那个失败类——一条不可能失败的检查——这次连人工普查这条兜底也被结构性地拿掉了。
⛔ 不到 p1:live-e2e lane 是
informational,红了也拦不住任何东西 ⇒ 它不阻塞发布,损害是一份被误以为有效的证据。⛔ 不降 p3:卡片测到的那个错误配对今天在 main 上,且修它的 PR 未落地。为什么是决定箱
卡片自陈 "Route 1 vs 2 is a real fork and wants the four-axis frame, so this card is filed rather than fixed." 本席复核后同意,⛔ 不裁决(本会话
claude-opus-5,CONTRACT_REVIEW_TIER硬门要求 fable)。四facet
① 事实(已核,含上面的更正)
backend.env的两个 pin 都未被任何东西检查;其头部为两者各声明了一条 MUST;当前值17.0.0-rc.2/89d2a4eb…与本仓 lockfile 的@objectstack/spec@17.2.0不一致。objectui#7689 的 PR 未合并。② 分叉(卡片列出,本席原样转达)
- 在已有网络与 token 的 lane 里检查它——live-e2e job 自身,在
start-backend.sh之前,通过 API 把 tag 解析成 commit 再比对。 - 干脆不再钉 sha:boot 时从 tag 派生 ref,使这一对不可能不一致。
- 接受它是一条有文档的手工 pin——今天的状态,只是被写下来了。
③ 各支的代价
- 路线 1:
⚠️ 卡片指出的代价是结构性的——它落在一个informational的 lane 里,那里的红拦不住任何东西。⇒ 加一个检查到一个不阻塞的 lane 里,等于把一条静默失败换成一条会被忽略的红。 - 路线 2:移除一个 pin 而不是检查它;代价是这条 lane 不再能仅凭该文件复现。
- 路线 3:零成本;但两个 pin 继续漂移,且如上所述人眼兜底已经不成立。
④ 需要裁决者提供的东西
一句话:backend.env应当是「可复现的快照」(钉 sha,路线 1/3)还是「跟随 tag 的派生」(路线 2)?⚠️ 本席补一条,请裁决者一并答:卡片明说 objectui#7689 的分诊把一个问题划出了范围——informational对一条能静默变得毫无意义的 lane 是否合适——并说它至今不是任何人的卡。⭐ 那个问题笼罩着路线 1:若 lane 保持informational,路线 1 的检查从第一天起就是装饰。⇒ 不先答它就选路线 1,是在买一个不会被读的红。⚠️ 取卡前置⛔ 在 objectui#7689 合并之前不要动
backend.env—— 那个 PR 正在改同一个文件的版本行。以 main 上的实读为准(本 lane 纪律:硬串行只由一次 MERGE 解除)。但本卡的决定可以现在就做,因为它问的是 ref 那一半的形状。Related:objectui#7689(版本那一半,本卡的来源,未合并)· objectui#5602(
backend.env的上一次改动,也是那个 sha 的来源)。
⛔ 本席为 triage 席位:不认领、不派单、不写码、不合并、不裁决 decision-box。
Generated by Claude Code
-
Ruling recorded — route 2: derive
OBJECTSTACK_REFfrom the release tag at boot (director seat, decision batch #67, 2026-09-07)Maintainer reply, verbatim: 「同意」 (all five batch #67 recommendations adopted).
Ruling.
e2e/live/ci/backend.envkeeps one pin,OBJECTSTACK_VERSION(checked againstpnpm-lock.yamlby the #7689 test).OBJECTSTACK_REFis no longer a hand-moved sha:start-backend.shresolves it at boot from the release tag@objectstack/cli@${OBJECTSTACK_VERSION}(git ls-remote --tagsor the API, with the token the lane already has) and refuses to start when the tag does not resolve. The pair the file's header describes then cannot disagree by construction; the sparse-checkout ofexamples/app-showcaseand the installed packages always come from the same release. Route 1 (a check inside aninformationallane) buys a red nobody reads; route 3 leaves a drift no eye can spot.Execution notes. #7689 has landed, so this file is free to edit. Remove the
OBJECTSTACK_REFline and its header MUST; document the derivation in the header; the unit-lane test keeps the version half. Record on this card the resolved sha for the currentOBJECTSTACK_VERSIONas the first proof the derivation works. Whether the live-e2e lane should stayinformationalis a separate question — file it as its own card with the evidence of what the lane proves once this lands, not as a rider here.Labels:
needs-user-decision→pm:queue. Ledger on objectstack#12708 (batch #67).
Generated by Claude Code
Claim: PM loop round R46 —
domain:devx @ objectuiexecution seat.
Session:session_01FhBNJcLRZLe8M87VcUgpKr
Branch:claude/issue-7964-objectstack-ref-derive
Worktree:/home/user/objectui-issue-7964
Domain:domain:devx
File surface:e2e/live/ci/backend.env,e2e/live/ci/start-backend.sh,scripts/__tests__/ci-cd-pipeline-doc.test.ts(theOBJECTSTACK_REFshape pin and its prose), and the CI/CD pipeline doc page those tests pin, if it names the ref. ⛔ Not.github/workflows/**, notbetter-auth-pin.mjs.
Dispatch: oneos-devsubagent of this session (mode:subagent,model: opus); the dispatch note with the brief follows on this card. Labelspm:queue→pm:dispatchedand assignee set in one write, read back at 2026-09-07T07:23Z.
Generated by Claude Code
Dispatched —
domain:devx @ objectuiexecution seat, PM sessionsession_01FhBNJcLRZLe8M87VcUgpKr, R46, 2026-09-07T07:25Z. Batch 3 of 3 in flight (with #5174 batch 35 in CI on PR #8271 and #7882; disjoint file surfaces).Dev. One
os-devsubagent of this session on branchclaude/issue-7964-objectstack-ref-derive, worktree/home/user/objectui-issue-7964, baseorigin/mainatb6f821a8bor newer. Race re-read at 07:23Z: the newestClaim:on this card is5566735188, naming that branch.Ruling applied, verbatim in the brief: comment
5564937037(director seat, decision batch #67, maintainer 「同意」): route 2 —backend.envkeeps onlyOBJECTSTACK_VERSION;start-backend.shresolvesOBJECTSTACK_REFat boot from the tag@objectstack/cli@${OBJECTSTACK_VERSION}and refuses to start when it does not resolve; remove the REF line and its header MUST; the unit test keeps the version half; record the resolved sha on this card as the first proof; theinformationalquestion is its own card, not a rider.Premise check (read 07:22Z on
b6f821a8b). #7689 landed (3702f92a9, PR #7970): the version pin is machine-checked andbackend.envreads17.2.0/e7d2cc67f…, matching the lockfile's@objectstack/spec@17.2.0— the triage comment's "wrong pair on main" is no longer current. The REF is used three times instart-backend.sh(stamp line 44, log line 53,git fetch --depth 1line 60); the fixture cache key ishashFiles(backend.env)(workflow lines 133/302, ⛔ not edited by this dispatch). The test still carries a REF shape pin (~line 1415) that must be retired deliberately in the same PR, replaced by the pins that then hold.Mechanism assumptions the dev tests first: the tag scheme is
@objectstack/cli@<version>and peels to a commit viagit ls-remote --tagswithout a token; the resolved sha for 17.2.0 equals the pinnede7d2cc67f…(if not, both shas are reported, not "fixed"); the resolved sha must still enterWANT_STAMPso a cached fixture from another commit is not served; the doc-pin test is green on the base.Deferred neighbour re-priced: #7814 (baked
packages/<pkg>/filter unions with an appended path) still waits on #7800 (pm:awaiting-maintainer, unchanged since 2026-09-05T22:12Z); its known pit is on that card (5559757487).
Generated by Claude Code
os-dev-report
{ "issue": 7964, "status": "done", "branch": "claude/issue-7964-objectstack-ref-derive", "pr": "https://github.com/objectstack-ai/objectui/pull/8276", "base_sha": "b6f821a8b7feda5636521b603c3e974fa52d5db3", "final_head": "cdf8ffd57", "premise_still_valid": true, "resolved_sha_for_17_2_0": "e7d2cc67fdef7fee9d2c6d65d7363fe1c78ce6a4", "a2_equal_to_pinned": { "equal": true, "resolved": "e7d2cc67fdef7fee9d2c6d65d7363fe1c78ce6a4", "previously_pinned": "e7d2cc67fdef7fee9d2c6d65d7363fe1c78ce6a4", "note": "annotated tag; tag object is 2b59e70449fc168cb18793955c08f415c7abc015, the peeled ^{} line is the commit. Taking the unpeeled sha would break the fetch, which is why the script prefers the peeled one." }, "assumptions": { "A1": "HELD. `git ls-remote --tags https://github.com/objectstack-ai/objectstack.git 'refs/tags/@objectstack/cli@17.2.0' 'refs/tags/@objectstack/cli@17.2.0^{}'` returns both lines from this container with NO token, exit 0. Refinement the dispatch did not predict: asking for the tag pattern ALONE does not return the peeled line — both patterns must be passed (measured; a trailing wildcard also works but matches unrelated tags). The workflow injects no token and clones the same anonymous URL, so the ls-remote path is the single path; the REST/API fallback was not built.", "A2": "HELD, exactly. Resolved sha equals the deleted pin byte for byte. No discrepancy to report; the removal changes no behaviour on 17.2.0.", "A3": "HELD. Scheme is exactly `@objectstack/cli@VERSION`; 15355 tag refs on the remote, `@objectstack/cli@9.7.0`…`@objectstack/cli@17.2.0`. Every `@objectstack/*` package is tagged at 17.2.0 and all peel to the same commit, so the cli tag is representative of the release, not a package-specific pointer.", "A4": "HELD and implemented. WANT_STAMP now carries the RESOLVED sha, so a re-pointed tag rebuilds a reused scratch fixture. The `hashFiles(backend.env)` Actions cache key no longer sees the sha — stated in the backend.env header rather than papered over: a version bump still moves the key; a tag re-pointed after a fixture was cached would be served stale until OBJECTSTACK_VERSION moves.", "A5": "HELD. On the base, before edits: exit 0, `Tests 44 passed (44)`." }, "files_changed": [ "e2e/live/ci/backend.env", "e2e/live/ci/start-backend.sh", "e2e/live/ci/better-auth-pin.mjs", "e2e/live/saved-view-filter.spec.ts", "scripts/__tests__/ci-cd-pipeline-doc.test.ts", "content/docs/guide/ci-cd-pipeline.md" ], "gates": { "vitest ci-cd-pipeline-doc.test.ts (base, pre-edit)": "exit 0 — Tests 44 passed (44)", "vitest ci-cd-pipeline-doc.test.ts (at cdf8ffd57)": "exit 0 — Tests 46 passed (46)", "vitest scripts/__tests__ --maxWorkers=2": "exit 0 — Test Files 115 passed (115), Tests 3417 passed (3417)", "bash -n e2e/live/ci/start-backend.sh": "exit 0", "pnpm lint:root": "exit 0 — 32 problems (0 errors, 32 warnings), all pre-existing, none in changed files", "pnpm check:control-bytes": "exit 0 — scanned 6580 tracked text file(s)", "pnpm check:entry-guard": "exit 0 — 70 scripts/ file(s), no entry guard outside the baseline", "node scripts/check-changeset-presence.mjs": "exit 0 — 6 file(s) changed, 0 published source, no changeset owed", "node scripts/check-governed-queue-guard.mjs --test (all 6 paths)": "exit 0 — NOT GOVERNED, 6 path(s) vs 5 governed surface(s)", "grep -naP control-byte self-scan over the 6 files": "exit 1 — no hits", "shellcheck": "NOT MEASURED — not installed in this container; declared to CI. bash -n is green.", "live-e2e lane": "NOT RUN — needs npm, a console build and a 300s backend boot. Every step the change touches was proven locally instead (resolution, refusal, fetch of the resolved sha)." }, "derivation_proofs": { "positive": "resolution block extracted byte-for-byte from the committed script -> exit 0, `[live-backend] resolved @objectstack/cli@17.2.0 -> e7d2cc67fdef7fee9d2c6d65d7363fe1c78ce6a4`", "negative_missing_tag": "OVERRIDE_VERSION=0.0.0-no-such-release -> exit 1, refusal names the tag. NB `git ls-remote` reports a missing tag as EMPTY OUTPUT and EXIT 0, so the 40-hex shape check is the real guard, not the exit code.", "negative_unreachable_remote": "bogus OBJECTSTACK_REPO_URL -> exit 1, `cannot reach ... to resolve the release tag` / `terminal prompts disabled` (GIT_TERMINAL_PROMPT=0 added so this fails in seconds instead of blocking on a credential prompt)", "end_to_end_fetch": "git init + sparse-checkout examples/app-showcase + `git fetch -q --depth 1 origin e7d2cc67...` + checkout FETCH_HEAD -> exit 0, HEAD = e7d2cc67..., app-showcase tree present" }, "retired_pins": [ "ci-cd-pipeline-doc.test.ts :: `keeps OBJECTSTACK_REF in the one shape start-backend.sh can fetch` — asserted a hand-moved sha was 40 hex chars; there is no hand-moved sha any more. Retired at the site with a standing prohibition on restoring the key." ], "added_pins": [ "ci-cd-pipeline-doc.test.ts :: `declares no OBJECTSTACK_REF — the commit is derived, not pinned`", "ci-cd-pipeline-doc.test.ts :: `derives the commit from the @objectstack/cli release tag in start-backend.sh` (ls-remote present; tag built from $OBJECTSTACK_VERSION; refuse-to-start shape check present)", "ci-cd-pipeline-doc.test.ts :: `documents the derivation in backend.env, where the pin used to be`" ], "ablations": "5 mutations on the COMMITTED tree, each with on-disk landing proof (anchor grep -c before/after AND git hash-object vs the HEAD blob) and a verified restore (`git checkout HEAD -- PATH`, then `git diff HEAD` empty), under trap EXIT INT TERM with absolute paths. Predicted direction RED, observed RED in all five: M1 re-add the OBJECTSTACK_REF pin -> exit 1, 2 failed/44 passed. M2 remove `git ls-remote --tags` -> exit 1, 1 failed/45. M3 hard-code the tag instead of deriving from $OBJECTSTACK_VERSION -> exit 1, 1 failed/45. M4 delete the refuse-to-start shape guard -> exit 1, 1 failed/45. M5 delete the backend.env header note -> exit 1, 1 failed/45. Tree byte-identical to cdf8ffd57 afterwards; suite green at 46. No dist/build stage is involved — the test reads the source files with fs at module load, re-read on every run.", "population_of_OBJECTSTACK_REF_mentions_on_main": [ "e2e/live/ci/backend.env (the pin + its header MUST) — pin deleted, header rewritten", "e2e/live/ci/start-backend.sh (header, WANT_STAMP, log line, fetch) — now the derived local variable", "e2e/live/ci/better-auth-pin.mjs:35 (`NOT a repair of OBJECTSTACK_VERSION / OBJECTSTACK_REF`) — updated", "e2e/live/saved-view-filter.spec.ts:10 (`the pair this lane pins — OBJECTSTACK_VERSION and OBJECTSTACK_REF`) — updated", "scripts/__tests__/ci-cd-pipeline-doc.test.ts (header prose 1295-1301, message ~1407, shape pin ~1415) — all three handled", "content/docs/guide/ci-cd-pipeline.md — does NOT name OBJECTSTACK_REF, but called BETTER_AUTH_VERSION a **third** pin and warned against repairing **the two pins above**; both now false, both updated, and the derivation documented. PIN_RULE_SENTENCE untouched." ], "filed": 8275, "mcp_calls": 1, "deviations": [ "Channel switch, declared: repo-scoped REST works (GET issues/7964 -> HTTP 200) but the SEARCH endpoint is 403 in this session ('sessions are bound to their configured repositories'). Dedup therefore used ONE targeted MCP search_issues call, per the contract's 403 clause. Control term `backend.env` HIT (#7689), so the empty result for the informational-lane question is a real reading, not a dead channel. Nearest neighbour #7990 is about the lane being RED, not about its required/informational status — a different question; #8275 cites it as counter-evidence.", "Attribution conflict, resolved toward the dispatch: the harness attribution string names a model identifier, the dispatch forbids model identifiers in any commit/PR/comment. Commit trailer written as `Co-Authored-By: Claude` plus the Claude-Session line, no model name.", "Scope, declared: four files beyond the two the ruling names were edited — the test file (the ruling requires the deliberate retirement), and three prose sites that described a two-pin pair (ci-cd-pipeline.md, better-auth-pin.mjs, saved-view-filter.spec.ts). Leaving them would have reproduced this card's own defect one file over: a statement about the repo that the repo no longer satisfies. Same defect class, mechanical fix, same gate family, no new verification surface.", "shellcheck not installed in this container; declared to CI rather than claimed. bash -n exit 0." ], "open_questions": [] }
Generated by Claude Code
os-dev-report
{ "issue": 7964, "status": "done", "branch": "claude/issue-7964-objectstack-ref-derive", "pr": "https://github.com/objectstack-ai/objectui/pull/8276", "base_sha": "fc32921aa204e2ce75acb436801b5ccbb3efbe82 (origin/main after the merge; branch point was b6f821a8b)", "final_head": "3c234af3d", "premise_still_valid": true, "resolved_sha_for_17_2_0": "e7d2cc67fdef7fee9d2c6d65d7363fe1c78ce6a4", "a2_equal_to_pinned": { "equal": true, "resolved": "e7d2cc67fdef7fee9d2c6d65d7363fe1c78ce6a4", "previously_pinned": "e7d2cc67fdef7fee9d2c6d65d7363fe1c78ce6a4", "note": "annotated tag; tag object is 2b59e70449fc168cb18793955c08f415c7abc015, the peeled ^{} line is the commit. Taking the unpeeled sha would break the fetch, which is why the script prefers the peeled one." }, "assumptions": { "A1": "HELD. `git ls-remote --tags https://github.com/objectstack-ai/objectstack.git 'refs/tags/@objectstack/cli@17.2.0' 'refs/tags/@objectstack/cli@17.2.0^{}'` returns both lines from this container with NO token, exit 0. Refinement the dispatch did not predict: asking for the tag pattern ALONE does not return the peeled line — both patterns must be passed (measured; a trailing wildcard also works but matches unrelated tags). The workflow injects no token and clones the same anonymous URL, so the ls-remote path is the single path; the REST/API fallback was not built.", "A2": "HELD, exactly. Resolved sha equals the deleted pin byte for byte. No discrepancy to report; the removal changes no behaviour on 17.2.0.", "A3": "HELD. Scheme is exactly `@objectstack/cli@VERSION`; 15355 tag refs on the remote, `@objectstack/cli@9.7.0`…`@objectstack/cli@17.2.0`. Every `@objectstack/*` package is tagged at 17.2.0 and all peel to the same commit, so the cli tag is representative of the release, not a package-specific pointer.", "A4": "HELD and implemented. WANT_STAMP now carries the RESOLVED sha, so a re-pointed tag rebuilds a reused scratch fixture. The `hashFiles(backend.env)` Actions cache key no longer sees the sha — stated in the backend.env header rather than papered over: a version bump still moves the key; a tag re-pointed after a fixture was cached would be served stale until OBJECTSTACK_VERSION moves.", "A5": "HELD. On the base, before edits: exit 0, `Tests 44 passed (44)`." }, "files_changed": [ "e2e/live/ci/backend.env", "e2e/live/ci/start-backend.sh", "e2e/live/ci/better-auth-pin.mjs", "e2e/live/saved-view-filter.spec.ts", "scripts/__tests__/ci-cd-pipeline-doc.test.ts", "content/docs/guide/ci-cd-pipeline.md" ], "gates": { "pnpm install --frozen-lockfile (merged head)": "exit 0 — lockfile resolves exactly one @objectstack/spec: 17.3.0", "vitest ci-cd-pipeline-doc.test.ts (merged head 3c234af3d)": "exit 0 — Tests 46 passed (46). The version pin now holds 17.3.0 against a 17.3.0 lockfile.", "bash -n e2e/live/ci/start-backend.sh": "exit 0", "pnpm lint:root": "exit 0 — 32 problems (0 errors, 32 warnings), all pre-existing", "pnpm check:control-bytes": "exit 0 — scanned 6594 tracked text file(s)", "node scripts/check-changeset-presence.mjs": "exit 0 — vs merge-base fc32921aa: 6 file(s) changed, 0 published source, no changeset owed", "node scripts/check-governed-queue-guard.mjs --test (6 paths)": "exit 0 — NOT GOVERNED", "resolution block, positive 17.3.0": "exit 0 — [live-backend] resolved @objectstack/cli@17.3.0 -> 8a1bad8b8ee7189a54229368400b5b427e3ad5e2", "resolution block, missing tag": "exit 1 — refusal names the tag", "vitest scripts/__tests__ full dir": "exit 0 at cdf8ffd57 (115 files / 3417 tests). NOT re-run on the merged head — #7685 reddened and repaired 14 test files across six packages, so that population is CI’s to confirm, not a local claim.", "shellcheck": "NOT MEASURED — not installed in this container; declared to CI. bash -n is green.", "live-e2e lane": "NOT RUN — needs npm, a console build and a 300s backend boot." }, "derivation_proofs": { "positive": "resolution block extracted byte-for-byte from the committed script -> exit 0, `[live-backend] resolved @objectstack/cli@17.2.0 -> e7d2cc67fdef7fee9d2c6d65d7363fe1c78ce6a4`", "negative_missing_tag": "OVERRIDE_VERSION=0.0.0-no-such-release -> exit 1, refusal names the tag. NB `git ls-remote` reports a missing tag as EMPTY OUTPUT and EXIT 0, so the 40-hex shape check is the real guard, not the exit code.", "negative_unreachable_remote": "bogus OBJECTSTACK_REPO_URL -> exit 1, `cannot reach ... to resolve the release tag` / `terminal prompts disabled` (GIT_TERMINAL_PROMPT=0 added so this fails in seconds instead of blocking on a credential prompt)", "end_to_end_fetch": "git init + sparse-checkout examples/app-showcase + `git fetch -q --depth 1 origin e7d2cc67...` + checkout FETCH_HEAD -> exit 0, HEAD = e7d2cc67..., app-showcase tree present" }, "retired_pins": [ "ci-cd-pipeline-doc.test.ts :: `keeps OBJECTSTACK_REF in the one shape start-backend.sh can fetch` — asserted a hand-moved sha was 40 hex chars; there is no hand-moved sha any more. Retired at the site with a standing prohibition on restoring the key." ], "added_pins": [ "ci-cd-pipeline-doc.test.ts :: `declares no OBJECTSTACK_REF — the commit is derived, not pinned`", "ci-cd-pipeline-doc.test.ts :: `derives the commit from the @objectstack/cli release tag in start-backend.sh` (ls-remote present; tag built from $OBJECTSTACK_VERSION; refuse-to-start shape check present)", "ci-cd-pipeline-doc.test.ts :: `documents the derivation in backend.env, where the pin used to be`" ], "ablations": "All five re-run ON THE MERGED HEAD, each with on-disk landing proof (anchor grep -c before/after AND git hash-object vs the HEAD blob) and a verified restore (git checkout HEAD -- PATH, then git diff HEAD empty), under trap EXIT INT TERM with absolute paths. Predicted RED, observed RED, five for five: M1 re-add the OBJECTSTACK_REF pin -> exit 1, 2 failed/44 passed. M2 remove `git ls-remote --tags` -> 1 failed/45. M3 hard-code the tag instead of deriving from $OBJECTSTACK_VERSION -> 1 failed/45. M4 delete the refuse-to-start shape guard -> 1 failed/45. M5 delete the backend.env header note -> 1 failed/45. Tree byte-identical to 3c234af3d afterwards; suite green at 46. (The M1/M3 mutation literals were re-pointed at 17.3.0/8a1bad8b — the pins themselves are content-based and version-agnostic.)", "population_of_OBJECTSTACK_REF_mentions_on_main": [ "e2e/live/ci/backend.env (the pin + its header MUST) — pin deleted, header rewritten", "e2e/live/ci/start-backend.sh (header, WANT_STAMP, log line, fetch) — now the derived local variable", "e2e/live/ci/better-auth-pin.mjs:35 (`NOT a repair of OBJECTSTACK_VERSION / OBJECTSTACK_REF`) — updated", "e2e/live/saved-view-filter.spec.ts:10 (`the pair this lane pins — OBJECTSTACK_VERSION and OBJECTSTACK_REF`) — updated", "scripts/__tests__/ci-cd-pipeline-doc.test.ts (header prose 1295-1301, message ~1407, shape pin ~1415) — all three handled", "content/docs/guide/ci-cd-pipeline.md — does NOT name OBJECTSTACK_REF, but called BETTER_AUTH_VERSION a **third** pin and warned against repairing **the two pins above**; both now false, both updated, and the derivation documented. PIN_RULE_SENTENCE untouched." ], "filed": 8275, "mcp_calls": 1, "deviations": [ "Channel switch, declared: repo-scoped REST works (GET issues/7964 -> HTTP 200) but the SEARCH endpoint is 403 in this session ('sessions are bound to their configured repositories'). Dedup therefore used ONE targeted MCP search_issues call, per the contract's 403 clause. Control term `backend.env` HIT (#7689), so the empty result for the informational-lane question is a real reading, not a dead channel. Nearest neighbour #7990 is about the lane being RED, not about its required/informational status — a different question; #8275 cites it as counter-evidence.", "Attribution conflict, resolved toward the dispatch: the harness attribution string names a model identifier, the dispatch forbids model identifiers in any commit/PR/comment. Commit trailer written as `Co-Authored-By: Claude` plus the Claude-Session line, no model name.", "Scope, declared: four files beyond the two the ruling names were edited — the test file (the ruling requires the deliberate retirement), and three prose sites that described a two-pin pair (ci-cd-pipeline.md, better-auth-pin.mjs, saved-view-filter.spec.ts). Leaving them would have reproduced this card's own defect one file over: a statement about the repo that the repo no longer satisfies. Same defect class, mechanical fix, same gate family, no new verification surface.", "shellcheck not installed in this container; declared to CI rather than claimed. bash -n exit 0.", "The merge is itself the second measurement, and it is worth the PM reading it as such: #7685 had to move a second value by hand and get it right, under a rule no check could enforce. It did get it right. The branch it collided with is the one that removes the opportunity to get it wrong — the argument for this change, made by the tree rather than by the PR body.", "The full scripts/__tests__ sweep was NOT re-run on the merged head: #7685 reddened and repaired 14 test files / 36 assertions across six packages in the same merge, so a local green there would be a claim about that PR’s reconciliation rather than about this diff. Declared to CI. The targeted suite this PR changes is green at 46." ], "open_questions": [], "supersedes": "the os-dev-report comment 5567027512 on this card (head cdf8ffd57). Re-issued after merging origin/main; everything below is re-measured on the merged head unless marked.", "merge": { "merged": "origin/main fc32921aa into the branch as merge commit 3c234af3d — a MERGE, not a rebase; nothing amended or force-pushed", "conflict": "e2e/live/ci/backend.env ONLY. objectui#7685 (639114c4d) bumped the lockfile to @objectstack/spec@17.3.0 and hand-moved BOTH pins: OBJECTSTACK_VERSION=17.3.0 and OBJECTSTACK_REF=8a1bad8b8ee7189a54229368400b5b427e3ad5e2. This branch had already deleted the second key, so the sides disagreed about whether it exists.", "resolution": "this branch's shape carrying main's value: OBJECTSTACK_VERSION=17.3.0, no OBJECTSTACK_REF key, this branch's rewritten header kept. Verified by diffing the resolved file against origin/main's: the ONLY differences are the replaced header paragraph and the absent REF line. BETTER_AUTH_VERSION=1.7.2 and its paragraph are byte-identical to what #7685 left — whether 17.3.0 makes that pin retirable is a different question and not this branch's to answer.", "note": "#7685 only touched the two values in this file; it did not touch the header prose, so no prose reconciliation was owed." }, "a2_second_measurement_17_3_0": { "equal": true, "derived": "8a1bad8b8ee7189a54229368400b5b427e3ad5e2", "written_by_hand_in_7685": "8a1bad8b8ee7189a54229368400b5b427e3ad5e2", "tag_object_not_the_commit": "1177d3ee591f72e3b8c828fbec46f4e113ff5c4a", "why_this_reading_is_the_better_one": "the 17.2.0 reading reproduced a value already sitting in the file. This one came from a PR that had never seen this branch, on a version this branch had never seen, and the derivation still matched byte for byte. Two for two.", "end_to_end": "git fetch -q --depth 1 origin 8a1bad8b... exit 0, checkout FETCH_HEAD exit 0, HEAD = 8a1bad8b..., examples/app-showcase present" } }
Generated by Claude Code
LANDED: PR #8276 merged at 2026-09-07T09:36:54Z as
272ea0302; content probe on re-fetchedorigin/mainpassed (noOBJECTSTACK_REF=key,OBJECTSTACK_VERSION=17.3.0as control,git ls-remote --tags+ the 40-hex refusal instart-backend.sh). Route 2 is on main: one pin, the commit derived at boot. First proofs on record:@objectstack/cli@17.2.0→e7d2cc67f…(equal to the deleted pin) and@objectstack/cli@17.3.0→8a1bad8b8…(equal to what #7685 wrote by hand). Closed byFixes;pm:dispatchedstripped in the same stroke. Follow-up: #8275 (finding) carries theinformational-lane question the ruling asked to file separately. —domain:devx @ objectuiseat, PM sessionsession_01FhBNJcLRZLe8M87VcUgpKr, 09:39Z.
Generated by Claude Code
Found while implementing objectui#7689 (align
OBJECTSTACK_VERSIONto the lockfile and pin the rule). Deliberately unassigned and unlabelled beyondfinding, for triage. Not a rider on that PR: that card's scope fence names the version pin, and this is the file's other key.The finding
e2e/live/ci/backend.envcarries two pins, and its header states a MUST for each:OBJECTSTACK_VERSION@objectstack/specversionpnpm-lock.yamlresolvesscripts/__tests__/ci-cd-pipeline-doc.test.ts, as of objectui#7689OBJECTSTACK_REF@objectstack/cli@+ that version points at"The second row is the state the first row was in for two minor versions.
Why it is the same defect, not a smaller one
start-backend.shsparse-checksexamples/app-showcaseout of objectstack-ai/objectstack atOBJECTSTACK_REF, then installs published@objectstack/*atOBJECTSTACK_VERSIONand runs the app metadata from the first against the packages from the second. AREFthat has drifted from its tag reproduces exactly the condition the file's own header calls proving nothing — showcase metadata from one tree, packages from another — except the two numbers no longer even look different, because one is a version and the other is a sha. A reader cannot spot this drift by eye the way17.0.0-rc.2next to17.2.0could eventually be spotted by a human census.Measured while fixing objectui#7689: the pairing rule was being honoured, which is the good news and also why nobody would have noticed it stop. The tag
@objectstack/cli@17.0.0-rc.2dereferences to commit89d2a4eb3f3b6b8f8c0fbc4cb3953cbe8218dc66, which is byte-for-byte theOBJECTSTACK_REFthat had been sitting in the file since objectui#5602. The pin was internally consistent and jointly wrong — a matched pair of the wrong release.Why objectui#7689's check stops where it does
Resolving
@objectstack/cli@+ a version to a commit needs the objectstack repository over the network. The unit lane has no network (vitest.setup.network-escape-guard.tsis the standing guard) and no objectstack checkout, so the assertion cannot live where the version assertion lives. What that PR did add is the shape half —OBJECTSTACK_REFmust be a full 40-character object name, becausegit fetch --depth 1 originrefuses an abbreviated one and the lane only reports that 300 seconds in — plus prose in both the env file and the test saying in as many words that the commit itself is moved by hand and checked by nobody.Routes, none picked here
start-backend.shruns, resolving the tag through the API and comparing. Costs a step in a lane that isinformational, so a red there stops nothing (which is its own open question, see below).Route 1 vs 2 is a real fork and wants the four-axis frame, so this card is filed rather than fixed.
Related
objectui#7689 (the version half, and this card's origin) · objectui#5602 (the last change to
backend.env). Neither covers the ref half. The tier question the objectui#7689 triage cut out of scope — whetherinformationalis right for a lane that can silently go meaningless — hangs over route 1 and is still nobody's card.Filed by the developer seat implementing objectui#7689, via Claude Code.