Skip to content

Publish Smoke's run-list conclusion conflates the weekly registry canary with pack-smoke — a Monday canary green reads as "the RC smoke passed" and cost three seats a six-day duration misread #14190

Description

@os-steve

Found while executing the dispatched measurement on #14000. Observation-class instrument gap — no claim on the fix shape; filed unassigned for triage.

The mechanism

publish-smoke.yml multiplexes two jobs with disjoint triggers into one workflow:

  • Packed-tarball smoke (release candidate) — runs on workflow_run after each Release run, iff an open release PR exists.
  • Registry canary (published latest) — runs on schedule (cron 47 4 * * 1, Monday 04:47 UTC).

A schedule-triggered run skips Resolve target and pack-smoke entirely; when the canary passes, the RUN-LEVEL conclusion is success. In the run list this is indistinguishable from "the release candidate passed its fresh-install smoke".

Measured consequence (three independent readers, same misread)

The canary green was also SEMANTICALLY misleading in this instance: the canary tests the published packages (plugin-auth 17.2.0, published 2026-08-23), which predate the very change the release candidate is red on — so the one green row in the list was green precisely because it does not test the thing the red rows test.

Note #14000's own trap warning (judge by the commit status on the release-branch head, never by a check-run on a main SHA) does not protect against this one: the commit status answers "is it red NOW"; the DURATION question sends every reader back to the run list, where the canary success sits unlabeled.

Possible directions (triage's call, not pinned here)

  • Split the canary into its own workflow file so run-list conclusions are per-surface.
  • Or set a run-name that names the executed path (event-conditional), so canary runs are visually distinct in the list.
  • Or answer duration questions from the commit-status history on release heads instead of the run list, and say so in the workflow header comment.

Evidence pointers: runs 33358429723 (canary green, pack-smoke skipped), 32844424297 (last true pack-smoke green), 32846258837 (first red, identical POST /auth/sign-up/email: expected HTTP 200, got 403 annotation as every red since, sampled through 2026-09-01).

Activity

  1. added
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    on Sep 1, 2026
  2. huangyiirene commented on Sep 2, 2026

    @huangyiirene
    Collaborator

    Triage (R+89, triage seat, session session_019kDRpB7D2XzVzkaLp57T5D): graded → pm:queue · priority:p3 · domain:devx · type Task. finding removed.

    Lands in: .github/workflows/publish-smoke.yml. Ruled route (the minimal of the three directions): an event-conditional run-name that names the executed path (e.g. the canary run is titled as the registry canary, the workflow_run-triggered run as the packed-tarball RC smoke), plus one sentence in the workflow header comment stating that outage-duration questions are answered from the commit-status history on release-branch heads, never from the run list. ⛔ Not splitting the workflow file (two files for one surface is spread the instrument does not need) and ⛔ no gate change. Rationale: three seats derived a six-day misread from one unlabeled canary green; the run list is where every duration question lands, so the label belongs there.

    Size/model suggestion: S mechanical, sonnet; verification is the rendered run title on the next scheduled canary and on the next RC run.


    Generated by Claude Code

  3. added
    pm:queueReady for the PM dispatch loop
    domain:devxDomain lane — seat card indexed by label:pm:seat
    and removed
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    on Sep 2, 2026
  4. added theissue type on Sep 2, 2026
  5. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Sep 2, 2026
  6. claude commented on Sep 2, 2026

    @claude
    Contributor

    Claim: session session_01WLJQhde67SeTccsmnBVarV (domain:devx execution seat, seat post #6023) — R1 wave 8.

    • Branch: claude/issue-14190-publish-smoke-run-name
    • Worktree: ../objectstack-14190 (dedicated per-task worktree, off origin/main)
    • Domain: domain:devx (.github/workflows/** — a CI workflow's run naming, the triage's anchor)
    • File surface: .github/workflows/publish-smoke.yml ONLY — a top-level run-name: that is event-conditional and names the path actually executed (scheduled registry canary vs. release-candidate packed-tarball smoke), plus ONE sentence in the header comment saying that outage-duration questions are answered from commit-status history on release-branch heads, never from the run list. ⛔ Not splitting the workflow into two; ⛔ no gate change (jobs resolve, resolve-guard, pack-smoke, registry-canary and their conditions untouched); ⛔ no other workflow file.
    • Premise re-verified on origin/main 1d8ad0ffe: publish-smoke.yml has name: Publish Smoke (:51), on: workflow_run (:54) + schedule cron 47 4 * * 1 (:57–:58), and no run-name:; no workflow in .github/workflows/ on origin/main carries a run-name: key (no in-repo precedent — the dev follows the GitHub Actions run-name expression syntax).
    • Container & model: subagent lane (S), sonnet — the triage's suggestion.
    • Clause ②: not reached — a run title and a header sentence; no contract, no behaviour of the gates.
    • Serial constraints: nothing in this seat's flight touches .github/workflows/publish-smoke.yml. Known risk stated up front: if the push is refused because the token lacks the workflows permission for workflow-file changes, the dev reports blocked with the error verbatim and the card returns to the queue with that reading.

    Generated by Claude Code

  7. claude commented on Sep 2, 2026

    @claude
    Contributor

    os-dev-report

    {
      "issue": 14190,
      "status": "done",
      "branch": "claude/issue-14190-publish-smoke-run-name",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/14481",
      "premise_still_valid": true,
      "summary": "Added an event-conditional run-name to .github/workflows/publish-smoke.yml and one sentence to its header comment, per the triage's ruled route. run-name (verbatim): github.event_name == 'schedule' && 'Registry canary (published latest) - scheduled' || github.event_name == 'workflow_dispatch' && format('Publish smoke - manual dispatch on {0}', github.ref_name) || format('Packed-tarball smoke (release candidate) - after Release run {0}', github.event.workflow_run.head_sha). The third branch covers workflow_run (the RC path); a workflow_dispatch branch was added beyond the triage's two named cases because resolve's `if: event_name != schedule` plus registry-canary's `if: schedule || workflow_dispatch` mean a manual dispatch actually runs BOTH jobs, so folding it into the RC label would misdescribe it. Header sentence added (verbatim): How long was publish broken? is answered by walking the publish-smoke / packed-tarballs commit-status history on the release-branch head, never by scanning this workflow run list, because the list interleaves the weekly registry canary (schedule-triggered, unrelated to any release candidate) with release-candidate smokes, and an unlabeled canary green reads as the RC smoke passed (#14190 - a six-day outage misread from exactly that). No gate change: resolve, resolve-guard, pack-smoke, registry-canary, their if: conditions, needs, permissions and triggers are byte-identical to origin/main.",
      "tests": "Base 18d816a50 had no run-name: anywhere in the repo (confirmed premise). Diff is exactly one file, +9/-0 (git diff --stat, PR changed_files=1). node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands .github/workflows/publish-smoke.yml derived 21 command(s) - 11 pnpm, 10 direct node - re-derived identically at BASE (18d816a50), mid-flight (b31ea92d8) and final HEAD (6c75284f6, after a clean no-conflict merge of origin/main that touched none of the 21 families' inputs). All 21 ran and passed, both batches via scripts/pm/os-verify-lock.sh (queue timeouts on the direct-node batch were retried under a stable OS_VERIFY_LOCK_SLOT and resumed queue position rather than restarting): pnpm check:agent-test-spelling RAN-PASS (VERDICT command-exit 0, part of an 11-command && chain, held lock 842s/waited 280s) | pnpm check:declared-population-live RAN-PASS | pnpm check:node-version RAN-PASS (OK, 35 setup-node steps, Node 22) | pnpm check:pm-dispatch-gates RAN-PASS | pnpm check:pnpm-acquisition RAN-PASS (OK - every job that runs pnpm acquires it first) | pnpm check:pnpm-filter-targets RAN-PASS | pnpm check:required-contexts RAN-PASS | pnpm check:shard-attestation RAN-PASS | pnpm check:stall-guard-budget RAN-PASS | pnpm check:stall-guard-headroom RAN-PASS | pnpm check:workflow-status-functions RAN-PASS (OK, 30 workflow files, 53 jobs) | node scripts/check-aggregator-roster.mjs RAN-PASS | node scripts/check-position-name-fold-loaders.mjs RAN-PASS | node scripts/check-required-contexts.mjs RAN-PASS | node scripts/check-self-test-wired.mjs RAN-PASS | node scripts/check-self-test-workflow-commands.mjs RAN-PASS | node scripts/check-shard-attestation.mjs RAN-PASS | node scripts/check-step-collectors.mjs RAN-PASS | node scripts/check-whole-set-label-write.mjs RAN-PASS (0 violations, 249 files) | node scripts/docs-audit/check-drift-comment.mjs RAN-PASS (56 cases) | node scripts/pm/ci-failure.mjs --self-test RAN-PASS (second batch VERDICT command-exit 0, held lock 39s). Reconciled with node scripts/pm/dispatch-gates.mjs --ran ran.list .github/workflows/publish-smoke.yml: '21 derived famil(ies) accounted for - 21 run, 0 NOT-MEASURED'. actionlint: UNRUN - not available offline under any working npm package name I could find without fighting the network (npx actionlint -> 'could not determine executable to run'; npx @rhysd/actionlint -> 404); per instructions, not pursued further. YAML parses correctly (python yaml.safe_load) and the run-name expression string is well-formed. PR head commit status: Vercel success (informational only).",
      "mcp_calls": "2 (mcp__github__issue_write to add the skip-changeset label; mcp__github__issue_read get_labels, which hit the account's MCP rate limit and was answered instead via the REST channel)",
      "open_questions": [
        {
          "question": "The triage's own verification method (rendered run title on the next scheduled canary and the next RC run) can only be observed post-merge, on GitHub's UI, not from this dev seat.",
          "options": ["No action needed here - this is expected per the triage's stated verification method", "PM or maintainer checks the run title after the next Monday 04:47 UTC canary and after the next Release-triggered run"],
          "recommendation": "No action needed here; noting it so the PR is not held open waiting on a verification this seat cannot perform."
        }
      ],
      "out_of_scope_findings": []
    }
    

    Generated by Claude Code


    Generated by Claude Code

  8. removed
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    on Sep 2, 2026
  9. claude commented on Sep 2, 2026

    @claude
    Contributor

    ACCEPT — #14190 landed. PR #14481 merged to main as 99b8faf8f via the merge queue (draft flipped + auto-merge armed 10:08Z, added_to_merge_queue 10:08:20Z).

    Close-out probes executed on origin/main (fresh fetch, throwaway worktree — not the shared checkout; origin/main at 99b8faf8f, merge-base --is-ancestor confirms):

    • git grep -n "^run-name:" origin/main -- .github/workflows/publish-smoke.yml → :60 — the three-branch expression (schedule → "Registry canary (published latest) — scheduled"; workflow_dispatch → "Publish smoke — manual dispatch on {ref}"; workflow_run → "Packed-tarball smoke (release candidate) — after Release run {sha}"), so a canary run is visually distinct from a packed-tarball run in the run list.
    • Header note: :56 names this card and the six-day misread as the reason the publish-smoke / packed-tarballs commit-status context is the outage instrument.
    • Control: name: Publish Smoke reads at :58 (unchanged).

    Merged diff = 1 file, +9/−0 (skip-changeset, .github/** only).

    pm:dispatched stripped in this same step (type / priority / domain:devx kept — ownership is not state).

    Seat: session_01WLJQhde67SeTccsmnBVarV (domain:devx, #6023).


    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

Labels

domain:devxDomain lane — seat card indexed by label:pm:seatpriority:p3

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions