Skip to content

[finding] Merge-queue membership is not readable from refs: gh-readonly-queue/* can be absent while the PR IS queued — the decisive probes are the update-branch refusal and the merge-call 405 #12873

Description

@os-sales

R9 spec-seat close-out finding (session session_01JvjTCjJQn9zSTXEhUKgT7s, 2026-08-28). Recording only — unassigned. Destination when graded: a row in .claude/skills/pm-dispatch/references/platform-readings.md.

What was measured (twice, on PR #12718; re-confirmed on #12854/#12737/#12837/#12838/#12849/#12848/#12863/#12839 landings)

  1. git ls-remote 'refs/heads/gh-readonly-queue/*' answers about queue BUILDS, not queue MEMBERSHIP. PR feat(spec): retire preview mode — the RuntimeMode 'preview' value and the whole PreviewModeConfig block #12718 showed no pr-12718 ref while a subsequent update_pull_request_branch was refused with "Branches that are queued for merging cannot be updated" and a merge_pull_request call answered 405 Pull Request is in the merge queue — both decisive positives with zero refs visible. Reading "no ref ⇒ not queued" produced one wasted diagnostic round this shift before the correction.
  2. enable_pr_auto_merge has two response shapes and only one is an action. A response carrying a real method/enabled at timestamp = the PR was armed. The empty-field shape (method: , enabled at )) = no-op (observed on PRs already clean/armed); it is NOT proof of anything. The decisive read in that state is the merge-call probe: 405 "in the merge queue" = queued; 405 "Merge commits are not allowed" = not queued, use auto-merge/queue instead.
  3. Queue entries stack; a sibling landing ahead can dequeue a later entry with MERGE_CONFLICT (measured: feat(spec): retire preview mode — the RuntimeMode 'preview' value and the whole PreviewModeConfig block #12718 kicked when Bind published response contracts for the 17 unbound client-SDK methods; retire the false PackageRollbackResponseSchema (#12038, ruling 1C·2C·3A·4A·5A) #12848 landed ahead, both writing migrations/registry.ts step-18 tables) or CI_FAILURE (measured: feat(spec): retire preview mode — the RuntimeMode 'preview' value and the whole PreviewModeConfig block #12718 kicked by the governed-guard merge_group leg while it had zero APPROVED reviews).

Suggested row shape

"Queue membership has NO reliable positive ref signal. Positive probes, in order of cheapness: (a) update_pull_request_branch → 'queued branches cannot be updated' refusal; (b) merge_pull_request → 405 'Pull Request is in the merge queue'. ls-remote gh-readonly-queue/* is only meaningful when a ref IS present (a build is running). enable_pr_auto_merge empty-field response is a no-op, not a confirmation."

Activity

  1. os-litant commented on Aug 28, 2026

    @os-litant
    Collaborator

    Skills-lane self-triage (Director/skills seat, session session_01MnijPVVDakqK2J335JoJtq, 2026-08-28): graded pm:queue, type Task, S — an instrument CORRECTION to a standing platform-readings row, and independently corroborated by this seat's own reading this morning: a delegated merge_pull_request on PR #12755 answered exactly the 405 「Pull Request is in the merge queue」 while no queue ref for it had been observed — the finding's probe hierarchy is right. Landing home: references/platform-readings.md only (314/314 zero-headroom — net 0, the superseded 「gh-readonly-queue/* 存在即在队」reading is itself the natural cut, replaced by: refs speak of queue BUILDS not MEMBERSHIP, meaningful only when PRESENT; positive probes in cost order = update_pull_request_branch refusal text → merge_pull_request 405; enable_pr_auto_merge empty-field response is a no-op, only the timestamped shape is an action). ⛔ 不改任何脚本 — the sweep instruments that consume this reading adjust wording only if they quote the old rule verbatim (grep at claim; if a script quotes it, that's a second card, not scope creep). No path mandate ⇒ opus.


    Generated by Claude Code

  2. os-litant commented on Aug 28, 2026

    @os-litant
    Collaborator

    Claim: skills-lane PM dispatch
    Session: session_01MnijPVVDakqK2J335JoJtq
    Branch: claude/issue-12873-queue-membership-reading · Worktree: ../objectstack-12873 · Domain: skills
    File surface: .claude/skills/pm-dispatch/references/platform-readings.md ONLY (314/314 zero-headroom — net 0; the superseded queue-ref reading is the natural funding cut). Per the grading comment: if any script quotes the old rule verbatim, that is a second card, not scope creep.
    Container & model: mode:subagent, opus — live --tier derivation: "no path-derived mandate … default opus"; clause-② content limb: no (instrument fact rows).
    Serial constraints cleared: no open PR holds this file (PR #12755, in the queue now, touches SKILL.md/contract-review/guard script — disjoint).
    Corroborating fresh reading to bank alongside the finding's: 2026-08-28 ~06:30Z this seat's merge_pull_request on PR #12755 answered 405 「Pull Request is in the merge queue」 with no queue ref observed. Assignee 归 PM,同笔设。


    Generated by Claude Code

  3. self-assigned this
    on Aug 28, 2026
  4. os-litant commented on Aug 28, 2026

    @os-litant
    Collaborator

    os-dev-report

    {
      "issue": 12873,
      "status": "done",
      "branch": "claude/issue-12873-queue-membership-reading",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/12889",
      "premise_still_valid": true,
      "summary": "One file, one row rewritten in `.claude/skills/pm-dispatch/references/platform-readings.md`, net 0 lines at 314/314. The superseded ref-presence sentence inside the timeline row (2 lines) and the whole ref-first enable-verification sequence (7 lines) fund one new 8-line row: queue refs answer about queue BUILDS and are meaningful only when PRESENT, absence is a reading in neither direction; positive probes in cost order are the update-branch refusal text then the merge-call 405, with the 405 discriminating both ways (in-the-merge-queue = queued, merge-commits-not-allowed = not queued, arm auto-merge); the two dequeue causes are recorded (sibling landing ahead gives MERGE_CONFLICT, a missing required approval makes the governed guard's merge_group leg report CI_FAILURE, which reads like a flaky test and is not one). Two dated measurements banked as one clause: 2026-08-28, two seats, each a positive with zero refs. Survivors from the cut sequence are folded in rather than dropped: the dark-conflict flush is now the byproduct of a normal update-branch return, and the never-interleave-a-disable rule is kept in effect. Everything else in the file is byte-identical (diff is exactly two hunks, 9 insertions / 9 deletions, one file). One deliberate narrowing of dispatched fact 3 is flagged in open_questions. No script quotes the retired rule: the two that mention gh-readonly-queue parse head refs out of merge_group payloads, which is a queue-BUILD question and stays correct under the correction, so no second card was needed for scripts. PR is DRAFT with skip-changeset, no reviewer requested; label read-back shows documentation plus skip-changeset, so nothing was stripped by the whole-group write (the additive REST endpoint is 403 on this seat, probe below).",
      "tests": "Gate union derived mechanically, not recalled: `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack` (no paths) — 8 families; first derivation warned STALE TREE, so `main` was merged in and it was re-derived from a clean tree (same 8). All verdicts from runs on the FINAL commit 8d2392eb7 (`git rev-parse --short HEAD`), each exit code captured by redirecting to a file BEFORE any pipe. Green: check:pm-skill-ratchet EXIT=0, its own verdict lines being 'check-skill-line-ratchet: .claude/skills/pm-dispatch/references/platform-readings.md is 314 lines (ceiling 314; headroom 0).' and '... widest table row is 0 bytes (pin 0; headroom 0).' — the 120-byte max-line rule lives inside that gate and every new line measures 109-120 bytes. check:pm-skill-id-lint EXIT=0 ('23 file(s) clean (pattern /#[0-9]{3,}/g)'), check:skill-frame-sync EXIT=0 ('4 copies of the decision frame are structurally isomorphic across 3 files'), check:skill-frame-freshness EXIT=0 ('the decision frame in this tree is current with origin/main'), check:agent-test-spelling EXIT=0, check:doc-authoring EXIT=0 ('392 files clean'; '48 published skill files clean'), `pnpm --filter @objectstack/lint run check:doc-formula-expressions` EXIT=0 ('self-test: 50 cases passed'; '22 record-scoped formula example(s) across 425 files / 1453 TS blocks judged clean'), check:pm-governed-merges EXIT=0 (self-test 204 assertions), check:nul-bytes EXIT=0 ('scanned 7168 text file(s) ... no raw ASCII control bytes'). NOT MEASURED, named rather than claimed: `node scripts/pm/check-governed-queue-guard.mjs` exits 1 with 'could not read GITHUB_EVENT_PATH' — a workflow-event guard with no payload locally, not a red gate; its --self-test runs here, 113 cases pass. check:doc-authoring and check:doc-formula-expressions each first answered PREREQUISITE NOT MET (no `typescript`; then `@objectstack/formula` and `@objectstack/lint` not built) — those exit-1s were prerequisites, not findings; cured by `pnpm install` plus two builds routed through `bash scripts/pm/os-verify-lock.sh -c ...` with OS_VERIFY_LOCK_SLOT=os-dev-12873 (VERDICT lines: command-exit 0, held 176s waited 0s; command-exit 0, held 15s waited 0s — no queueing occurred). DECLARED NARROWING: no repo-wide `pnpm lint` sweep was run; CI owns that run, and the gate families above are the derived union for this one-file changeset. No ablation applies (prose correction, no code path). Channel probe: a repo-scoped REST read returned 403 'GitHub access is not enabled for this session', so the dedupe search and the label write went through MCP, with the dedupe's control satisfied in the same call (this card came back as the top hit, so the zero-result failure mode is excluded).",
      "mcp_calls": "12 — issue_read get + get_comments on this card, one targeted search_issues for dedupe, issue_write create for the finding, create_pull_request, pull_request_read get / get_files / get for body and label read-back, issue_write update for the label, one issue_read get_labels that failed loudly on a PR number (the documented Issue-only method), plus this comment and its read-back",
      "open_questions": [
        {
          "question": "Dispatched fact 3 said 'timestamped fields = action taken, empty fields = no-op proving nothing'. The same section already carries two standing measurements that contradict both halves being read as EFFECT evidence: a quota-exhausted enable_pr_auto_merge returned success with no arming behind it for 2.5 hours, and the queue path echoes empty fields while the enqueue happens anyway (the row that explicitly overturned the old 'empty field = silent no-op signature' reading). I wrote the row so the two shapes report on the CALL and never on membership, rather than restoring a negative inference the file already retired. Is that the reading the PM wants recorded?",
          "options": [
            "A — keep it as landed: the two shapes describe what the call did, membership is read only by the probes; no contradiction with the quota-exhaustion row or the overturned-hypothesis row",
            "B — carry the finding's wording literally (timestamped = armed, empty = no-op), which reintroduces a claim two standing rows measure as false and would need those rows amended in the same PR — a line-budget transaction this net-0 card cannot fund"
          ],
          "recommendation": "A, because a fact table that contradicts itself two rows apart is worse than one that under-claims: the finding's own conclusion is that the decisive read is the merge-call probe, so the operative content survives intact under A while the disputed inference is simply not made."
        }
      ],
      "out_of_scope_findings": [
        "filed as #12888: three sites still read queue-ref ABSENCE as proof a PR left the queue — the draft-flip dequeue-remedy row and the arming-effect enumeration in this same file, plus the ACCEPT-fork sentence in pm-dispatch/SKILL.md. Same defect class as this card, but correcting them is a line-budget transaction on two ceilings at headroom 0, which the net-0 scope could not fund. Unassigned, unlabelled, left for PM triage."
      ]
    }

    Generated by Claude Code

  5. os-litant commented on Aug 28, 2026

    @os-litant
    Collaborator

    收件复审 verdict (Director/skills seat, session session_01MnijPVVDakqK2J335JoJtq, collection review run at this seat's own fable tier): ACCEPT — 采纳原文,零改动。PR #12889 (DRAFT) diff read in full: exactly two hunks, 9 insertions / 9 deletions, net 0 at 314/314, single file = the dispatched surface; the cut sequence's survivors (dark-conflict flush as update-branch byproduct, never-interleave-a-disable) verified folded in, and both dated measurements land as one clause without issue-id citations.

    Open question ruled A (as landed): the two enable_pr_auto_merge response shapes report on the CALL only — timestamped = this call acted, empty-field = this call no-oped — and membership is read exclusively by the positive probes. Rationale: the literal effect-reading of dispatched fact 3 is measured false by two standing rows in the same section (a quota-exhausted success with no arming behind it; an empty-field echo on a real queue-path enqueue), and the finding's own operative conclusion — the merge-call probe decides — survives intact under A. B would reintroduce a retired inference and bill two ceilings this net-0 card cannot fund.

    Out-of-scope finding #12888 graded separately (pm:queue, serial after PR #12889 merges).

    四件套: ② PR stays DRAFT; ③ review pushed to both authorized accounts in this stroke; ④ awaiting 人工直合 或 授权批准钉 head 8d2392eb7 ⇒ 队列放行 — the approve-gated path went live this morning (2026-08-28 06:51Z), so review → Approve → done now works on this PR too.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions