Repository navigation
Description
Filing gate ①: a defect with a named landing point. Filed by domain:devx seat 1 (#6023, session_012zwsLMxQBwHUYJgPyrpEvx), following its own reading on #23274 (6148507314) and #23294's dev report (6150858863). Triage may re-grade it on first touch. ⛔ This is not a claim.
Reader who acts: the domain:devx execution seat. Surface: scripts/pm/ci-failure.mjs and its self-test only.
What was measured
node scripts/pm/ci-failure.mjs --run 38411694784exits 2. For the roster jobLint & Repo Gatesit printsNONE of its members was found among this sha's check-runs. It printed this twice: once at this seat's triage of the hourly red, and again in tooling(pm): dispatch-gates' scratch-dir scan reads a.d.tsdeclarationexport function mkdtempSync(prefix: string)as a call site, so the full battery reds on main since PR #23273 #23294's dev run.- The red member does exist.
GET /commits/042ef51530/check-runs?check_name=Lint · PM dispatch-gatesreturns 3 rows:- success
115338637229(run38409754946) - failure
115345404875(run38411694784, the asked run) - a later cancelled
115345950501(run38411617233)
- success
- Read on
mainbae5841bce:walkInto(:1860) runslatestPerName(all). That function keeps the newest row per name across every run on the sha.:1931then passes thatkeptset tomemberLanes(…, kept, { runId }).memberLanes(:1067) discards every row from a run other thanrunId.- So the asked run's red member has already been replaced in
keptby the newer cancelled row from run38411617233. That row is then filtered out by run id, andmatchedcomes back 0.
- The tool sends the reader to "open the job URL" with no answer. The member rows the walk listed hold the answer, but the walk drops them.
What done looks like
- An aggregator's members are matched against the rows of the aggregator's own run, read from the full list for the sha (
all), not from the newest-per-name set across runs. Within that run, the newest row per member name still wins, so a re-run inside the run is still handled. - Re-running
--run 38411694784listsLint · PM dispatch-gates(115345404875, failure) as the member that did not succeed. - The self-test pins the case: a fixture sha with a later, cancelled same-name row in another run. The aggregator's red member is still found. The control: a member whose newest row in the aggregator's own run is green reads as succeeded.
latestPerName's existing role is unchanged: the sha-level failing list still ignores superseded rows.- ⛔ No new gate.
Workload: S. The precedents are #23249 (roster jobs, PR #23253) and #23223 (Lane verdict, PR #23246), both on the same file.
四维(业务立场)
- 长远合理性:分诊工具按「聚合器自己那次 run」读成员,是 tooling(pm): ci-failure.mjs's isRosterJob misses the
Verify every … lane succeededaggregator steps, so their substitute prints a heredoc that reproduces nothing #23249 已立的口径(memberLanes的 run-id 过滤),只是喂错了输入集;修输入,不加旁路。 - 实际业务拉动:main 红时席位第一步就跑这个工具;它答「找不到成员」,席位只能手翻日志(本卡两次实测)。
- 防 AI 犯错:工具给出确定的红成员,AI 席位不再凭猜测去读另一个 run 的取消行。
- 创业阶段不扩散:一处输入集改动加一条自测,不加门禁、不加脚本。
Dedupe: REST listing labels=domain:devx&state=all&since=2026-10-01, titles grepped for ci-failure|roster|aggregator. It returned #23249 (closed: roster jobs not classified) and #23223 (closed: Lane verdict resolution). Neither is this input-set defect. Dedupe words: ci-failure roster members not found · superseded same-name check-run · memberLanes kept set · --run grouping across runs.
Activity
objectstack-fleet commentedon Oct 13, 2026
Claim: PM loop round 19 (serial) ·
domain:devxseat 1 · 2026-10-13T20:36Z · seat-filed (category ①)Session:
session_012zwsLMxQBwHUYJgPyrpEvxAccount:
zhuangjianguo(the seat's linked user, asGET /userreports it; this card's assignee as of this act)Branch:
claude/issue-23305-roster-members-own-runWorktree:
objectstack-issue-23305Domain:
domain:devxSeat:
domain:devx#1File surface:
scripts/pm/ci-failure.mjs(walkIntoand thememberLanescall, ~:1931) and its self-test only. ⛔ No.github/workflows/**. ⛔latestPerName's sha-level role does not change.Container & model:
S,mode:subagent,model: opus(dispatch-gates --tieronscripts/pm/**: no path-derived mandate)Clause-②: no (internal PM tooling)
Responsibility:
memberLanesfilters rows by run id afterlatestPerNamehas already dropped the right one, so no existing check sees the loss.maingets "NONE of its members was found" and has to read the logs by hand (measured twice on run38411694784).Thread-read: none
Serial constraints cleared: no open PR touches
scripts/pm/ci-failure.mjs; I read every open PR's file list at this act. docs(permissions): authentication.mdx "How enforcement works" says only the REST server and the runtime dispatcher block an ADR-0069-held session — the raw-host route families gate too since PR #23200 and PR #23285 #23288's dev has returned, and its PR docs(permissions): the "How enforcement works" callout names every transport seam that consults the ADR-0069 gate #23333 is accepted (6154680467) and armed. That makes this the seat's only dispatch in flight (serial order6146552291).objectstack-fleet commentedon Oct 13, 2026
os-dev-report
{ "issue": 23305, "status": "done", "branch": "claude/issue-23305-roster-members-own-run", "pr": "https://github.com/objectstack-ai/objectstack/pull/23337", "session": "session_012zwsLMxQBwHUYJgPyrpEvx", "premise_still_valid": true, "summary": "Reproduced on main cc14657ede and fixed in scripts/pm/ci-failure.mjs only, the card's landing point. memberLanes now takes the walk's whole check-run listing (new checkRunListing: every row in `all`, beside latestPerName's kept/superseded). It reads an aggregator's members from that aggregator's own run's rows in `all`, newest row per name inside the run. `kept` alone still decides the sha-level failing list, and latestPerName is untouched. A superseded red member is not in the failing list, so the roster verdict now names it by check-run id and job URL instead of saying 'its own row is above'. This change made that branch reachable, so it had to be fixed too. The row-set choice now lives inside the pure function, so the offline self-test can fail on the original defect (ablation A1). A fix made only at the call site would have been invisible to it (A4). Root cause as the card predicted, but wider than one row: all 8 Lint member names had their kept row from run 38411617233 (cancelled). Process notes: the worktree named in the dispatch did not exist, so I created it from origin/main cc14657ede. Commit trailers and the PR footer use AGENTS.md's model-free forms, not the harness reminder's. node_modules was removed before this report, and the worktree is removed with a plain `git worktree remove` (no --force) right after this comment.", "tests": "All runs at HEAD e29bf95658 (git rev-parse --short HEAD after the final commit; BASE cc14657ede). (1) Repro. Before, on main cc14657ede: `node scripts/pm/ci-failure.mjs --run 38411694784` EXIT=2, printing 'NONE of its members was found among this sha's check-runs'. After: EXIT=2, listing '✗ \"Lint · PM dispatch-gates\" (lint-pm-dispatch-gates) — failure; check-run 115345404875, NOT listed above: a later same-name row from run 38411617233 (check-run 115345950501, cancelled) supersedes it on this sha.' plus its job URL. The two outputs differ only in that roster block: the sha-level line '49 check-run(s) after grouping by name (106 rows on the sha, 57 superseded)', the failing list and the verdict are byte-identical. Mechanism probe, read-only GET /commits/042ef51530/check-runs (106 rows, 2 pages): for all 8 Lint member names, latestPerName keeps run 38411617233's cancelled row, started 14:15:56Z, over the asked run's row, started 14:14:50Z. The kept aggregator row is the asked run's 115353240189. (2) `node scripts/pm/ci-failure.mjs --self-test` EXIT=0. Battery 'roster verdict: the substitute names the member lanes' went 13 → 17 cases, with the pin equal to the registered count: a one-run probe with the pin at 18 printed 'registered 17 case(s), below its pinned floor of 18'. (3) Ablations via scripts/ablation-replace.mjs in wrap mode, after the fix commit. Each leg: anchor 1 → 0, blob moved. Each restore: blob == HEAD 07b4465c88c4, empty git diff HEAD, and git status --porcelain empty. A1, members read from listing.kept: expected and observed exactly 2 red (the red-member case and the render case). A2, in-run grouping removed: exactly 2 red (the red-member case and the control). A3, superseded render branch disabled: exactly 1 red (the render case). A4, the walk call site handed `kept` again: the offline self-test stayed EXIT=0, as predicted, because the walk is not exercised offline. The 1st live attempt is NOT MEASURED: the jobs API answered HTTP 502, so memberLanes was never reached. The 2nd live attempt was loud: \"Cannot read properties of undefined (reading 'filter')\" via the mid-walk net, EXIT=2, 'Nothing was judged'. (4) Gates. `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` derived 30 commands; all 30 exited 0. That includes pnpm check:pm-dispatch-gates ('fast 1839 case(s) in 370.5s', '1839 cases pass') and ci-failure --self-test. `--ran` with a per-line exit code: '30 derived famil(ies) accounted for — 30 run, 0 NOT-MEASURED (a DERIVED zero — all 30 recorded an exit code and none of them is 3)'. Outside the derived set, check-governed-merges reads this file's source (the proxy re-arm guard-spelling mirror): `pnpm check:pm-governed-merges` EXIT=0, 500 assertions. (5) Lint, as a proven narrowing. Population: the 1 touched file, which eslint.config.mjs lints and does not ignore. Count: `eslint --no-inline-config --format json` reports 1 file, 0 errors, 0 warnings. Invariance: the resolved config has no parserOptions.project and no projectService, so there is no type-aware linting. The full pnpm lint run is CI's. (6) Changeset: none, labelled skip-changeset. The root manifest is private; 0 of 71 non-private manifests holds the path; git grep of the new symbols under packages/** exits 1 with 0 hits. Positive control: `export const FieldSchema` in packages/spec/src/data/field.zod.ts, shipped by files[] src/**/*.zod.ts, exits 0. CI on PR #23337 at report time: 39 check-runs, 10 success, 11 skipped, 18 in_progress (Lint · PM dispatch-gates among them), 0 failure.", "mcp_calls": "0 — no MCP GitHub tool was called.", "api_writes": "3 relay dispatches from this session (POST /repos/objectstack-ai/objectstack/dispatches, via scripts/pm/fleet-write), executing 4 REST writes as objectstack-fleet[bot]: POST /repos/objectstack-ai/objectstack/pulls (draft #23337, body read back byte-identical); POST /repos/objectstack-ai/objectstack/issues/23337/assignees (zhuangjianguo); POST /repos/objectstack-ai/objectstack/issues/23337/labels (skip-changeset, via scripts/pm/label-write.mjs, read back MATCHES: size/m, skip-changeset); POST /repos/objectstack-ai/objectstack/issues/23305/comments (this report, via scripts/pm/post-stamped.mjs). Plus 2 git pushes of the branch, which are not REST: the empty-branch probe and e29bf95658.", "open_questions": [], "out_of_scope_findings": [ "class: a · reach: public door `node scripts/pm/ci-failure.mjs --run 38411694784` at e29bf95658, with a wrong answer measured. Three general sentences say the member rows are listed above, while the only row listed is the aggregator's (Lint & Repo Gates 115353240189). The three are: the ROSTER JOB banner ('The answer is in those members' rows, listed above'), the roster branch of the job-log line ('a verdict about the member jobs listed above, whose own rows already carry their assertions'), and the roster substitute line ('the member row(s) named above carry the answer, each with its own substitute'). The new lane line under them correctly says NOT listed above · evidence: landing points in scripts/pm/ci-failure.mjs: render()'s roster banner, sayLog's roster branch, and renderSubstitute's roster line. They were already false for this run before this PR; this change only made the lane line correct. Same family as this card (the ci-failure roster reading), so fold it into that family's closing card if one exists · dedupe words: ci-failure roster banner listed above · member rows not listed superseded · roster substitute each with its own substitute · ci-failure misleading roster text", "carrier: 承接者:无 · noted, not filed — the mid-walk net (midWalkVerdict) words a non-transport exception (a TypeError) as 'the transport failed after 106 check-run(s) had been listed'. Seen only on the ablated tree (A4), so it is a programming-error path; it is recorded in the PR's Acceptance notes only." ] }Generated by Claude Code
objectstack-fleet commentedon Oct 13, 2026
Review: ACCEPT · PR #23337 (draft, head
e29bf95658,Fixes #23305) ·domain:devxseat 1 ·session_012zwsLMxQBwHUYJgPyrpEvx· 2026-10-13T21:09ZI checked this on GitHub and read the diff myself; I did not rely on the report alone.
scripts/pm/ci-failure.mjs(+142 / −18).size/m,skip-changeset. The root manifest is private and 0 of 71 publishable manifests carry the path. A positive control is given.checkRunListingreturns{ all, kept, superseded }from one listing.latestPerNameis unchanged, andkeptalone still decides the sha-level failing list and pending count, as before.memberLanesnow takes the listing. It filtersallto the aggregator's own run first, then takeslatestPerNameinside that run, so a re-run within the run is still read at its latest attempt.listed.has(check)identity test is sound:kept,alland the in-run set share row references.walkInto), and nothing outside the file importsmemberLanes.--run 38411694784onmainprinted "NONE of its members was found".Lint · PM dispatch-gates(115345404875, failure), superseded by run38411617233's cancelled115345950501. The rest of the output is byte-identical.keptholds run 9's rows.kept) → 2 red.kept) stays green offline, as predicted: the walk is not exercised offline. The live repro above covers it.check:pm-governed-mergeswas also run (it reads this file's source) and passed 500 assertions. ESLint reports 0 errors.e29bf95658: 24 green, 11 skipped, 5 running, none red. Auto-merge is armed.sayLog's roster branch,renderSubstitute's roster line). They were already false for this run before this PR. I am filing them as one p3 card in the same family, in the same act.objectstack-fleet commentedon Oct 13, 2026
Landed: PR #23337 →
614fdec832(Fixes #23305) ·domain:devxseat 1 ·session_012zwsLMxQBwHUYJgPyrpEvx· 2026-10-13T21:32Zmain,scripts/pm/ci-failure.mjsis identical to the PR heade29bf95658.completed), andpm:dispatchedis removed.sys_memberis not one of the delegated-admin gate's governed objects, but the gate lists it and the same page's table says membership writes are tenant-admin-only #23323 in this seat's serial order.