Repository navigation
fix(pm): issue-transfer confirms a transfer on the target and reads a lagging old URL as a pending redirect - #21291
Merged
objectstack-fleet[bot] merged 1 commit intoOct 2, 2026
Conversation
…gging old URL as a pending redirect
The read-back read the SOURCE first and exited 4 ("the card did not move")
whenever the old URL still answered 200 -- which GitHub keeps doing for
minutes after a transfer lands. It now finds the card on the target: by the
number the transferIssue answer carried (direct), else the number the old
URL's 301 names, else by the pre-read's title among the target's cards
updated since the send (the relay, whose run reports the number only where a
seat container cannot read it). A card found there is exit 0 with the target
URL, the old URL's 200 printed as a pending redirect. The target is re-read on
a bounded schedule while it answers without the card; exit 4 is kept for a
target that still lacks the card after it while the old URL still serves it
from the source; an unreadable or ambiguous target is UNCONFIRMED (6). The
transfer is never re-sent.
Claude-Session: https://claude.ai/code/session_01FNKm1SmPpuJASnbjxWGtsJ
Co-authored-by: Claude <noreply@anthropic.com>
This was referenced Oct 2, 2026
objectstack-fleet
Bot
deleted the
claude/issue-21020-issue-transfer-readback-target
branch
October 2, 2026 02:43
This was referenced Oct 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #21020
Clause-②: no
What changed
scripts/pm/issue-transfer.mjsconfirmed a transfer by reading the source URL first. If the old URL still answered 200, it exited 4 with "the card did not move". GitHub keeps serving a moved card's old URL with 200 for minutes, so every measured transfer that landed reported exit 4. The read-back now confirms on the target. The old URL is printed beside the verdict and never decides it.transferIssueanswer (direct), or else the number the old URL's 301 names. Otherwise by the pre-read's title, among the target's cards updated since the transfer was sent. That is the relay path: its run reports the number only in a job log and step summary that a seat container cannot read. Pull requests are skipped. Two cards with the same title are not a confirmation.--jsongainspending_redirect.TRANSFER_READ_BACK_DELAYS_MS= 3 s, 7 s, 15 s (25 s in all). Each re-read prints one line. The transfer is never re-sent. The schedule copies the measured list lag of the relay'sissue_createread-back. The old URL's own lag is minutes, so the re-read does not wait for it.redirectTarget()also reads the repository from the/repos/OWNER/NAME/issues/Nspelling.scripts/pm/fleet-write/dispatch.mjsandexecute.mjsare not touched, and neither isdispatch-gates.mjs.Measurements (this session, 2026-10-02, read-only)
c7396f1a,issue-transfer.mjsL407-411 sent a 200 from the old URL straight toEXIT_BOARD_DISAGREES, before the target was ever read.moved.numberand used it only to compare against the redirect's number.Location: https://api.github.com/repos/objectstack-ai/hotcrm/issues/1972through1975.Locationand an emptyurl, so no number is available to this identity. That is the "301 naming no card" branch.GET /repos/objectstack-ai/hotcrm/issues/1972answers 403 "GitHub access to this repository is not enabled for this session". The same happens:Authorizationheader (the proxy replaces it: a bogus bearer still read objectstack#21020 with 200);/search/issuesalso answers 403.created_at/updated_at. The target was unreadable here. The title search listssort=updated&since=SENT-minus-60s. It rests on a transfer updating the card, which is not yet measured: the transfer gives the card a new number and a timeline event. It does not usesort=created, because a transferred card is expected to keep its original creation date.Tests: on
4b37ce1epnpm check:pm-issue-transfer(=node scripts/pm/issue-transfer.mjs --self-test) → exit 0:✓ issue-transfer self-test: 63 cases pass across 8 batteries.to.urlequal to the target URL andpendingRedirect: true, under both the direct and the relay transport.scripts/ablation-replace.mjsin wrap mode. Each mutation landed on disk (anchor 1 → 0, blob changed). Each was restored to blob == HEAD7cd9be392f56withgit diff HEADempty.npx eslint --no-inline-config --format json scripts/pm/issue-transfer.mjs→ exit 0: 1 file, 0 errors, 0 warnings.parserOptions{ecmaVersion: latest, sourceType: module}. No type-aware linting is set up, so this diff cannot change any verdict on an untouched file.pnpm lintis left to CI.node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commandson this tree derived 28 families. All 28 ran with exit 0.--ran(exit codes recorded): "28 derived famil(ies) accounted for — 28 run, 0 NOT-MEASURED (a DERIVED zero …)".check:pm-issue-transfer, the script's own suite.check:nul-bytesis OK, and a control-byte self-scan of the file found nothing.Acceptance notes
check:pm-issue-transfer. No workflow names it, andcheck:self-test-wiredcovers only scripts CI already runs. The local run above is this suite's only measurement. Carrier: none.dispatch.mjsand is not touched here.updated_atpremise of the title search (above). The first relay transfer from a session that can read the target settles it. Its read-back line says "found by that title" when the premise holds.Generated by Claude Code