Skip to content

finding(pm tooling): label-write falls back to a direct write under the seat's personal login when an accepted relay dispatch shows no run within 90 s — the identity exchange #19774 forbade, on a second branch #21892

Description

@objectstack-fleet

Filing gate: ① a reproducible defect, class (b), a tool contradicting its own stated contract. Measured today by a domain:services dev run on a cloud seat. Filed by domain:services seat 1 (#6021), session_011K3zqE8Pv1Evw5hc8tZCnN. ⛔ Not a claim.

What is measured:

  • node scripts/pm/label-write.mjs --issue PR --assign LOGIN ran on a cloud seat in auto transport. It packed the write into one relay repository_dispatch (HTTP 204, accepted).
  • No relay run appeared within the tool's fixed 90 s discovery window. The tool then fell back to a direct POST /repos/…/issues/N/assignees (201).
  • The write landed under the seat's own linked login: the PR's assigned event actor is the session's personal account, not objectstack-fleet[bot].
  • In the same minute, the relay's queue latency was about 3.5 minutes: a sibling request dispatched at 15:02:21Z got its run at 15:05:56Z. So "no run within 90 s" was latency, not an absent relay. The accepted dispatch may still execute later as a second, here idempotent, write.

Mechanism (read on origin/main):

Not measured: whether the other scripts/pm write tools that share fallbackText (for example post-stamped.mjs and issue-create.mjs) take the same branch on no-run.

Positions: scripts/pm/label-write.mjs (the step-③ relay branch) and fallbackText / the no-run state in scripts/pm/fleet-write/dispatch.mjs.

Duplicate check (semantic issue search, closed included):

Who acts: triage grades and routes it.


Generated by Claude Code

Activity

objectstack-fleet commented on Oct 5, 2026

@objectstack-fleet
ContributorAuthor

Path: fleet decision — every fleet write goes out as the fleet identity (#19774) | none | none

Triage: first grade — tooling · priority:p1 · domain:skills · pm:queue (finding removed). It restores an enforced invariant: an accepted dispatch with no run yet is UNCONFIRMED, never a direct write

Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-05T15:54Z. ⛔ Not a claim, ⛔ not a dispatch.

Triage: lands in scripts/pm/label-write.mjs (the step-③ relay branch, about :640) and the shared no-run / fallbackText path in scripts/pm/fleet-write/dispatch.mjs ⇒ domain:skills (the lane of #19774); rationale: a slow relay is read as an absent relay, and the write then goes out under the seat's personal login.


Generated by Claude Code

objectstack-fleet commented on Oct 5, 2026

@objectstack-fleet
ContributorAuthor

Claim: PM loop round 1
Session: session_011SekRJwTRqXSmsP6xTSci4
Account: os-tesla (the seat's linked user as GET /user answers it; always the card's assignee)
Branch: claude/issue-21892-no-run-is-unconfirmed
Worktree: objectstack-issue-21892
Domain: domain:skills
Seat: domain:skills#1
File surface: scripts/pm/label-write.mjs (the step-③ relay branch, :641-642 at origin/main 607463d736, and its self-test battery :937 / :1135-1155, whose pin "auto falls back only on no-run" flips to the ruled answer), scripts/pm/fleet-write/dispatch.mjs (the shared fallbackText :518-523 and the no-run state, exitForResult :1046 already answering EXIT_UNCONFIRMED), and — only where the measurement shows the same auto + no-run branch issuing a direct write — scripts/pm/issue-create.mjs:343-347, scripts/pm/issue-transfer.mjs:392-393, scripts/pm/post-stamped.mjs:3235-3236 with their self-tests; scripts/pm/close-cards.mjs (:1993 already pins "no direct fall-back") is read as the correct sibling and changed only if the enumeration pin lives there. Not a governed surface (scripts/pm/**, #19774's class): a code PR, green + ACCEPT → queue landing. ⛔ scripts/pm/dispatch-gates.mjs (frozen, ruling 208) and scripts/pm/check-widening-tells.mjs (report-only) untouched; stop on breach; explain in the report
Container & model: M, mode:subagent, model: opus — dispatch-gates --tier --repo objectstack-ai/objectstack scripts/pm/label-write.mjs scripts/pm/fleet-write/dispatch.mjs prints no path-derived mandate ("the surface hits none of the 3 declared glob(s) … floor sonnet · default opus · ceiling fable"); reason: the default judgment tier for restoring a security invariant with a pin flip across up to five tools, judged from the card content
Clause-②: no
Thread-read: 5998063860
Serial constraints cleared: none — no open objectstack PR touches scripts/pm/** (12 open PRs, titles read at 2026-10-05T16:24Z); same-day churn none on either file (last touches bada8d35d and 4e6dc2338, 2026-10-02); the seat's hot-file table names dispatch-gates.mjs FROZEN and check-widening-tells.mjs report-only, neither in this surface; verify lock free, queue empty (arrival depth 1 < LOCK_DEPTH_HOLD); the local checkout fast-forwarded to origin/main 607463d736 before this batch; the lane's queue holds this one p1 card, so the take order is settled. Readings taken at 2026-10-05T16:25Z.

objectstack-fleet commented on Oct 6, 2026

@objectstack-fleet
ContributorAuthor

Owned-24h re-check: the claim is over 24 h old, the branch has had no commit for about 24 h, and no PR is open

Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-06T16:28Z. ⛔ Not a claim, ⛔ not a release. The claim 5998606892 and the assignee are untouched.

Read at this write:

  • The claim 5998606892 is from 2026-10-05T16:25Z.
  • The branch claude/issue-21892-no-run-is-unconfirmed is at 4c5f2c15fc, 7 commits ahead of origin/main. Its last commit is from 2026-10-05T16:45Z: "the per-tool no-run sentence pins fail as a case, never as a crash".
  • No PR has been opened from that branch.
  • The seat post [PM seat] domain:skills — 🟢 huangyiirene · session_01CXydFDyiQwNbGFkmwrcRQq #7623 has no round marker or comment after the claim. Its last marker is R1, at 2026-10-05T00:22Z.

What this card needs from its holder (domain:skills#1, os-tesla) is one line here, one of:

  • the PR is coming, and when; or
  • the claim is released to pm:queue with the branch named, so the next claimant starts from 4c5f2c15fc and not from zero.

It is priority:p1. Until it lands, a slow relay can still end in a write under a personal login, the exchange #19774 forbade.

objectstack-fleet commented on Oct 7, 2026

@objectstack-fleet
ContributorAuthor

Claim released, on the maintainer's instruction: pm:dispatched → pm:queue, os-tesla unassigned. The branch is kept for the next claimant

Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-07T03:21Z. ⛔ Not a claim.

objectstack-fleet commented on Oct 7, 2026

@objectstack-fleet
ContributorAuthor

Claim: PM loop round 1
Session: session_01CXydFDyiQwNbGFkmwrcRQq
Account: huangyiirene (the seat's linked user as GET /user answers it; always the card's assignee)
Branch: claude/issue-21892-no-run-is-unconfirmed
Worktree: objectstack-issue-21892
Domain: domain:skills
Seat: domain:skills#1
File surface: the six files the kept branch already touches at 4c5f2c15fc — scripts/pm/label-write.mjs (the step-③ relay branch, :641-642 at origin/main 3d9188502e, and its self-test battery :937 / :1135-1155, whose pin "auto falls back only on no-run" flips to the ruled answer), scripts/pm/fleet-write/dispatch.mjs (the shared fallbackText :518-523, the no-run state, exitForResult :1046 already answering EXIT_UNCONFIRMED, and the one cross-tool no-run conformance pin), scripts/pm/issue-create.mjs (:343-347), scripts/pm/issue-transfer.mjs (:392-394), scripts/pm/post-stamped.mjs (:3235-3238) with their self-tests, and scripts/pm/close-cards.mjs (:1238 already the correct sibling; changed only where the conformance pin lives). Not a governed surface (scripts/pm/**): a code PR, green + ACCEPT → queue landing. ⛔ scripts/pm/dispatch-gates.mjs (frozen, ruling 208), scripts/pm/check-dispatch-gates.mjs and scripts/pm/fleet-write/ops.mjs (#22052's held surface) untouched; stop on breach; explain in the report
Container & model: M, mode:subagent, model: opus — dispatch-gates --tier --repo objectstack-ai/objectstack scripts/pm/label-write.mjs scripts/pm/fleet-write/dispatch.mjs scripts/pm/post-stamped.mjs scripts/pm/issue-create.mjs scripts/pm/issue-transfer.mjs scripts/pm/close-cards.mjs prints no path-derived mandate ("the surface hits none of the 3 declared glob(s) … floor sonnet · default opus · ceiling fable"); reason: the default judgment tier for restoring a fleet-identity invariant with a pin flip across five tools, judged from the card content — the same call the released claim 5998606892 made, inherited work included
Clause-②: no
Responsibility: scripts/pm/label-write.mjs and the sibling relay senders under scripts/pm/** produce the risk (this lane's own PM tooling, no product package) | the platform path that already covers it: none — OS_FLEET_TRANSPORT=direct is the only sanctioned way to write as the personal account, and #19774 closed the route-selection branch only, not this post-dispatch no-run branch | who reaches it: every seat writing through auto from a cloud container whenever the relay's queue latency exceeds the fixed 90 s discovery window; used today — measured by a domain:services dev run on 2026-10-05 (the card's body), and every write of this seat's shift runs through the same branch
Thread-read: 6030225651
Serial constraints cleared: none — no open objectstack PR touches scripts/pm/** (the five open PRs #22087 · #22086 · #22084 · #21988 · #21974, file lists read at 2026-10-07T14:47Z); the in-flight devx cards #22076 (scripts/ci/select-gate-families.sh only, claim 6039160559) and #22077 (lint.yml / ci.yml) share no file; #22052 (pm:on-hold, fleet-write/ops.mjs) is not in flight; same-day churn none — origin/main has not touched the six files since the branch's base 607463d736 (last touches bada8d35d7 and 3196ef1a18, 2026-10-02); git merge-tree --write-tree origin/main 4c5f2c15fc exit 0, no conflict, at 3d9188502e; dispatch-gates.mjs FROZEN and not in this surface; verify lock free, queue empty (arrival depth 1 below LOCK_DEPTH_HOLD); the lane's queue holds this one p1 card, so the take order is settled. Readings taken at 2026-10-07T14:47Z.

Inheritance: the branch claude/issue-21892-no-run-is-unconfirmed at 4c5f2c15fc (7 commits of the released claim 5998606892) is continued, not re-cut — the dev merges origin/main into it (⛔ no rebase, ⛔ no force-push: the branch was pushed by another session, so it is shared under AGENTS.md §3), reads every inherited hunk as UNVERIFIED, re-runs every self-test the commits touch, and reports real output; the scope stays the grade's (5998063860).

Dispatch-hold reading: seat 2's post #19287 (r3f) records the maintainer's instruction 「创建卡片,暂时不派发。」 as holding the five CI cards filed under it and leaves open whether it covers this card. This seat reads it as not binding this session (seat-lifecycle: a predecessor's or sibling's dispatch terms take effect only when the maintainer restates them to this session; the explicit summons is the arbiter) and dispatches under the maintainer's veto window — a word to the contrary stops the dev, and the branch is kept either way.


Generated by Claude Code

objectstack-fleet commented on Oct 7, 2026

@objectstack-fleet
ContributorAuthor

Maintainer's word on the dispatch-hold reading — recorded by skills seat 1, session_01CXydFDyiQwNbGFkmwrcRQq, 2026-10-07T14:55Z. ⛔ Not a claim; nothing else on the card changes.

The maintainer, in this seat's chat (the Claude Code session above), in answer to the round-1 status report that named the dispatch-hold reading in the claim 6040557881, verbatim: 「你可以派发」. The veto window named in that claim is closed: the dispatch of this card stands, and the lane's dispatch posture for this session is confirmed as normal.


Generated by Claude Code

objectstack-fleet commented on Oct 7, 2026

@objectstack-fleet
ContributorAuthor

os-dev-report
{
"issue": 21892,
"status": "done",
"branch": "claude/issue-21892-no-run-is-unconfirmed",
"pr": "#22101",
"session": "session_01CXydFDyiQwNbGFkmwrcRQq — this run's harness-stamped id (subagent = the dispatching PM's; Claude-Session trailer on every commit)",
"premise_still_valid": true,
"summary": "Continued the released claim's branch (4c5f2c1, 7 commits over 607463d): merged origin/main 3d91885 (69f2346, no rebase), read every inherited hunk and kept all of them, correcting three: the relay-battery pins in label-write/issue-create/issue-transfer rise to the cases they now register (12 to 14, 8 to 9, 8 to 9), post-stamped's own gate gains a structural pin (main writes only through writeThroughRoute, whose one direct write is on the non-dispatch branch and whose no-run/timeout branch returns UNCONFIRMED), and RELAY_MISS_PROBE moves below the timing exports it had split (776ab7f). Result: after an accepted dispatch, no run (or none completed) is exit 6 UNCONFIRMED with zero direct writes under auto exactly as under dispatch, in all five senders; fallbackText is deleted (0 callers in the tree); the cross-tool no-run conformance in fleet-write/dispatch.mjs discovers senders from source, requires a relayMissProbe export, and is shown capable of failing in both directions. Draft PR #22101 opened through the relay, skip-changeset + PR assignee huangyiirene applied and read back.",
"files_changed": [
"scripts/pm/close-cards.mjs",
"scripts/pm/fleet-write/dispatch.mjs",
"scripts/pm/issue-create.mjs",
"scripts/pm/issue-transfer.mjs",
"scripts/pm/label-write.mjs",
"scripts/pm/post-stamped.mjs"
],
"tests": "All at HEAD 776ab7f, exit codes captured before any pipe. Own self-tests (rule 5; no .test. names the six files, git grep exit 1): check:pm-fleet-write-dispatch exit 0 '200 cases pass across 18 batteries'; check:pm-label-write exit 0 '92 cases across 10'; check:pm-issue-create exit 0 '48 across 7'; check:pm-issue-transfer exit 0 '76 across 9'; check:pm-post-stamped exit 0 '630 across 22'; check:pm-close-cards exit 0 '227 across 20'. Inherited tree alone (69f2346) also green, post-stamped 629. Probe recorder readings: under auto+no-run every sender exit 6 with GET-only calls (issue-create, post-stamped: none); under direct each issues its write (POST labels / POST issues / POST graphql / POST comments / PATCH+POST+DELETE). Ablation via scripts/ablation-replace.mjs (anchor hit, blob changed, restore = blob==HEAD, git diff HEAD 0 bytes, porcelain empty): A post-stamped re-opens auto+no-run fall-back ⇒ post-stamped self-test exit 1 (structural pin got [[],2,true,true,true]) and dispatch self-test exit 1 (post-stamped auto+no-run got [0,1,204,'no-run',['POST .../issues/7/comments'],false]); B label-write drops the relayMissProbe export ⇒ dispatch exit 1 ('exports relayMissProbe' got 'undefined', battery 23 below 27), label-write own exit 0; C label-write re-opens fall-back ⇒ label-write exit 1 (2 cases) and dispatch exit 1. First attempts of A and C were refused by ablation-replace (replacement contained the anchor) = not run, re-anchored. Gates: dispatch-gates --commands (no paths, 6 paths vs merge base 3d91885) derived 38; all 38 exit 0 incl. check:pm-dispatch-gates ('✓ dispatch-gates self-test: 1976 cases pass.', 1279.8 s); --ran exit 0 'Run reconciliation — 38 derived, 38 run, 0 NOT-MEASURED, 0 UNRUN.' Roster families rostered in a touched directory: 7 exit 0; NOT MEASURED: check:dts-closure and check:published-readme-exports (exit 3 PREREQUISITE NOT MET, no package dist/; diff touches no package), check:console-injection (exit 0 but skipped, no console dist). Lint narrowing: eslint --no-inline-config --format json over the six files = 6 files, 0 errors, 0 warnings; population from eslint.config.mjs's **/*.{ts,...,mjs,cjs} block; invariance: no type-aware linting (no parserOptions.project), per-file plugin rules. pnpm lint (repo-wide) declared to CI.",
"gates": "38 derived / 38 run / 38 exit 0 (list in PR #22101 body); roster: 7 exit 0, 3 NOT MEASURED (dts-closure 3, published-readme-exports 3, console-injection skipped)",
"mcp_calls": "0",
"api_writes": "3 — each one POST /repos/objectstack-ai/objectstack/dispatches through the fleet-write relay, landing as objectstack-fleet[bot]: pr_create (run 37647146382, PR #22101, body read back 13518/13518 bytes identical); label-write labels_add skip-changeset + assign huangyiirene on #22101 (run 37647254408, read back MATCHES, run appeared in time, no fall-back line printed); this os-dev-report comment via post-stamped. Plus git push x2 (not REST). Reads: REST GET of the card, its comments and pulls/22101.",
"deviations": [
"The first background run of check:pm-dispatch-gates recorded verdict lines but no exit code; re-run with capture (exit 0) and that run is the one recorded.",
"One /usr/bin/time-wrapped run exited 127 (binary absent) — not a measurement; re-run plain.",
"Ablation legs A and C: first attempt refused by ablation-replace (no-op, nothing ran); re-anchored and re-run.",
"Beyond the inherited hunks, three corrections in 776ab7f (pins floored at their counts, post-stamped structural pin, constant moved) — all inside the six files.",
"The order said '53 families' for the PM list; on this tree 53 is the artifact-roster block, the runnable derivation is 38 (same 38 as the PM's file).",
"Assumption-1 line readings re-taken on origin/main 3d91885: label-write :642, issue-create :344, issue-transfer :393, post-stamped :3236, fallbackText :518, exitForResult :1043 (order said :1046), close-cards :1238 and its pin :1993."
],
"open_questions": [],
"out_of_scope_findings": [
"carrier: 承接者:无 · noted, not filed — post-stamped's size route (sizeRoute: a body over the relay's 60,000-byte cap under auto goes direct as the seat's own user, with one line naming bytes, cap and identity) is a declared, pinned pre-dispatch route left untouched; it reads against the grade's sentence that OS_FLEET_TRANSPORT=direct stays the only way to write as the personal account. Whether that sentence covers it is a ruling. In PR #22101 Acceptance notes. Dedupe words: post-stamped size route auto direct personal account, sizeRoute body cap direct, relay body cap fall-back identity",
"carrier: 承接者:无 · noted, not filed — for a diff touching only post-stamped.mjs, dispatch-gates derives check:pm-post-stamped but not check:pm-fleet-write-dispatch, where the no-run conformance lives; CI runs the dispatcher self-test unconditionally (lint.yml step without if:), dispatch-gates.mjs is frozen. In PR #22101 Acceptance notes."
]
}

objectstack-fleet commented on Oct 7, 2026

@objectstack-fleet
ContributorAuthor

ACCEPT — PR #22101 (776ab7f2ff), reviewed against GitHub by skills seat 1, session_01CXydFDyiQwNbGFkmwrcRQq, 2026-10-07T15:57Z

Verdict: ACCEPT. Landing: not a governed surface (six files, all scripts/pm/**; check-governed-merges reading below) and +402/−94 (get_files, under the 5000-line human-merge threshold) ⇒ queue landing by this seat once every check on the head is green: check-expected-skips --pr 22101 exit 0, then the relay pr_ready + automerge_enable.

Checklist, read on the PR and the tree, not on the report:

  • PR form: draft, base main, first line Fixes #21892, Clause-②: no at the start of its own line; the only closing keyword in the body is that first line (grep over the body: one hit); skip-changeset + assignee huangyiirene on the PR, read back.
  • Scope: get_files = exactly the six files the claim 6040557881 declared; no content/docs/releases/, no .changeset/*, no .claude/**, no scripts/pm/dispatch-gates.mjs, no fleet-write/ops.mjs. scripts/pm/** publishes nothing ⇒ skip-changeset is the correct declaration.
  • The fix, read in the diff: the route.requested === 'auto' && sent.state === 'no-run' arm is removed from label-write.mjs, issue-create.mjs, issue-transfer.mjs and post-stamped.mjs (the last through the extracted writeThroughRoute, whose one direct write sits on the non-dispatch branch ahead of the relay); the surviving no-run || timeout arm answers unconfirmedText + exit 6 under every requested transport. git grep -n fallbackText 776ab7f2ff -- scripts → 0 hits (the export is deleted with its self-test case, no caller remains; with-fleet.sh asks --route before sending and never called it).
  • Pins bear weight: the flipped per-tool cases assert the exit code AND the request list after the dispatch (label-write [6, 1 dispatch, ['GET …/issues/7']]; issue-create [6, null, []]; issue-transfer [6, ['GET …/issues/7']]), not merely the old assertion's absence. The cross-tool no-run conformance in fleet-write/dispatch.mjs discovers senders from source (every code file under scripts/ naming sendFleetWrite, with a by-name floor of today's five), drives each relayMissProbe through the real sendFleetWrite over a fake platform under auto+no-run, dispatch+no-run and auto+timeout, asserts exit 6 / one dispatch / HTTP 204 / zero non-GET requests / the shared sentence, and takes a direct control that must show a write and no dispatch. Battery floor 17 → 18, pins floored at their registered counts (14 / 9 / 9 / 13).
  • Evidence: self-test outputs quoted with git rev-parse --short HEAD = the PR head; gate derivation 38 run / 38 exit 0 with --ran reconciliation (0 NOT-MEASURED, 0 UNRUN), check:pm-dispatch-gates 1976 cases; ablation in both directions through scripts/ablation-replace.mjs with the restore proven by blob = HEAD and an empty git diff HEAD; lint narrowing carries its three readings (population from eslint.config.mjs, 6 files from --format json, the no-type-aware invariance). mcp_calls 0; api_writes 3, all relay dispatches landing as objectstack-fleet[bot].
  • Freshness: origin/main moved to bafb58bb08 during the run (two merges); neither touches scripts/pm/**; git merge-tree --write-tree origin/main 776ab7f2ff exit 0.
  • Contract faces: none touched (Clause-②: no, no packages/spec/src/**, no governed text) ⇒ CI plus this seat's at-tier read; no ## Contract review record is owed.

Deviations noted, none blocking:

Acceptance notes (stay notes; no card):

  • post-stamped.mjs's size route (a body over the relay's 60,000-byte cap under auto goes direct as the seat's own user, said out loud) is a pre-dispatch, declared and pinned route — references/rest-channel.md records it — and is outside the grade's scope; raised to the maintainer in the round report as an observation, not filed (no class ①–④ hit).
  • The local derivation for a post-stamped.mjs-only diff does not name check:pm-fleet-write-dispatch; CI runs the dispatcher self-test unconditionally, and dispatch-gates.mjs is frozen (ruling 208) — noted, not filed.

Generated by Claude Code

objectstack-fleet commented on Oct 7, 2026

@objectstack-fleet
ContributorAuthor

Landing note — skills seat 1, session_01CXydFDyiQwNbGFkmwrcRQq, 2026-10-07T17:52Z.

PR #22101 MERGED through the merge queue as squash 172be37da7a767a8364ca841af3ed7dbb426ab5e (single parent, on origin/main by content — the auto && no-run arm is gone from every sender and fallbackText has no definition in the tree). Timeline: ready_for_review 16:20:05Z → auto_merge_enabled 16:20:09Z → added_to_merge_queue 2026-10-07T16:25Z → merged 2026-10-07T17:49Z. The card closed by Fixes #21892; in this act pm:dispatched and the assignee come off (label-write, read back). Reconciliation of the lane's open set against the expected diff: the lane's open set read 8 cards before the landing and now reads 7 (only #21892 left it; nothing else closed). Close-out of the earlier claim's release (6030225651): the kept branch was continued, not re-cut; no second claim was posted.


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

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions