Skip to content

fix(bin): close Gerrit-landed backlog items with the change URL as a note - #6140

Merged
kunchenguid merged 4 commits into
kunchenguid:mainfrom
slnkjthien:fm/fm-gerrit-backlog-close-pr
Oct 1, 2026
Merged

kunchenguid merged 4 commits into
kunchenguid:mainfrom
slnkjthien:fm/fm-gerrit-backlog-close-pr

Conversation

@slnkjthien

@slnkjthien slnkjthien commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Intent

Fixes #6138.

On a project registered with forge=gerrit, cleanup of a landed task leaves its backlog item In flight. bin/fm-teardown.sh records the close as tasks-axi done <id> --pr <gerrit change url>, and tasks-axi (0.2.6) refuses the URL: "Task pr link must be a canonical pull request URL". The endpoint and worktree are cleaned up, but the item stays In flight, and the state/<id>.backlog-close record left behind fails the same way on every session-start replay, so the only way out is closing the item by hand. Every forge=gerrit landing hits this; it was first seen on the first production Gerrit landing after #5427 merged.

The item should close as Done with the Gerrit change URL still recorded on it, and a pending close record should replay to success. GitHub PR URLs keep closing with --pr exactly as today.

Related and not addressed: #5936, the same rejection for GitHub Enterprise PR URLs, which also cannot be registered or merge-polled.

What Changed

  • fm_backlog_done (bin/fm-backlog-transition-lib.sh) now rewrites --pr <gerrit change url> to --note "Gerrit change <url>" before it calls tasks-axi done. tasks-axi rejects that URL as a --pr link, so before this change teardown and replays of state/<id>.backlog-close both failed and left the item In flight. It now closes as Done, and the new fm_backlog_pr_is_gerrit_change uses fm_pr_url_parse to decide which URLs are Gerrit changes. GitHub PR URLs still go through --pr as before.
  • For held tasks (fm_backlog_retain), a Gerrit change URL goes only into the deliverable line and is no longer copied into the row's --pr field. bin/fm-captain-hold.sh answer passes a retained Gerrit URL as a Gerrit change <url> note on the done call instead of running update --pr. docs/captain-hold-lifecycle.md documents both behaviours.
  • New tests: done with a Gerrit URL in fm-backlog-atomicity, Gerrit teardown close and replay in fm-teardown, and retain/answer with a Gerrit URL in fm-captain-hold-lifecycle.

🤖 Generated with Claude Code

Risk Assessment

✅ Low: Gerrit change URLs are now rewritten to --note at the shared fm_backlog_done and fm_backlog_row_artifact_supported boundaries, which cover teardown close, replay of pending close records (fm_backlog_close_transition), retain mode and an early captain answer. GitHub --pr handling is unchanged, and no other code sends --pr to tasks-axi.

Testing

I ran the real teardown and session-start scripts in disposable homes from bin/fm-lab-home.sh, against the real tasks-axi 0.2.6, which refuses Gerrit --pr links. On this change a Gerrit landing closes as Done with the change URL kept as a note, a GitHub landing still closes with its pr link, and a stuck close record written by the base code replays to success. On the base commit the same Gerrit teardown and replay reproduce the issue. I did not drive the captain-held answer path live. It is covered by its new regression test, which passes along with the other two test files that carry the new Gerrit cases. The temp labs and the base archive were removed and the worktree is clean.

  • Live validation: ✅ go - 3 of 4 scenarios driven live against the product
Scenario Result Live Evidence
Teardown of a landed forge=gerrit task closes its backlog item as Done and keeps the Gerrit change URL on it ✅ pass live teardown-gerrit-after.txt: teardown rc=0, state: done, body: "Gerrit change https://gerrit.example.com/c/project/+/12345&#34;, pending close record absent. teardown-gerrit-base-65c75b0.txt shows the base…
Teardown of a landed GitHub PR task still closes with a --pr link ✅ pass live teardown-github-after.txt: state: done, links: "pr:https://github.com/example/repo/pull/7&#34;, body empty
A stuck close record that the old code wrote (arg=--pr <gerrit url>) replays to success at the next session start ✅ pass live replay-stuck-gerrit-record.txt: the base bootstrap prints BACKLOG_RECONCILE refusal and the item stays in_flight. The fixed bootstrap prints 'closed the backlog item for task-g1', the item is done wit…
A captain answer on a held Gerrit ship, given before the cleanup replay, closes the item with the change URL noted instead of failing ⏸️ untested no The prior payload did not establish a live result. This path was driven only by the regression test tests/fm-captain-hold-lifecycle.test.sh (which passes, using the real fm-captain-hold.sh with a task…
Evidence: Live teardown of a Gerrit landing (fixed): item Done, change URL recorded as a note

Source: Live teardown of a Gerrit landing (fixed): item Done, change URL recorded as a note

== before: tasks-axi show task-g1
  state: in_flight
  links: none
== bin/fm-teardown.sh task-g1  (FM_HOME=lab, real tasks-axi 0.2.6)
fm-gate-refuse: gate agent lifecycle permitted only against lab home /tmp/fm-lab.XZRbpY
●━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
●  WATCHER DOWN - SUPERVISION IS OFF
●  1 task(s) in flight, but no watcher has a fresh beacon (last beat: never, grace 300s).
●  Trust the emitted supervision protocol for this harness; do not use shell & for watcher repair.
●  This is a supervision warning only; the guarded operation WILL still run.
●  watcher supervision needs Stop-owned automatic recovery; inspect the hook registration and startup status before ending the turn.
●━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
/tmp/fm-lab.XZRbpY/proj: skipped: no origin remote
teardown task-g1 complete (window firstmate:fm-task-g1, worktree /tmp/fm-lab.XZRbpY/wt)
Backlog: task-g1 is closed in /tmp/fm-lab.XZRbpY/data/backlog.md. Run bin/fm-tasks-axi.sh ready for dependency-cleared candidates, check date gates, and dispatch only work whose blockers are gone and date is due.
teardown rc=0
== after: tasks-axi show task-g1 --full
task:
  id: task-g1
  title: gerrit landing
  state: done
  blocked: no
  blocked_by: none
  held: no
  hold_reason: "-"
  hold_kind: "-"
  hold_until: "-"
  kind: ship
  repo: "-"
  priority: "-"
  created: "-"
  closed: 2026-09-30
  deps: none
  links: none
  body: "Gerrit change https://gerrit.example.com/c/project/+/12345"
== pending close record: absent
LAB=/tmp/fm-lab.XZRbpY
Evidence: Live teardown of a Gerrit landing on base 65c75b0: bug reproduced (item stays In flight, record stuck)

Source: Live teardown of a Gerrit landing on base 65c75b0: bug reproduced (item stays In flight, record stuck)

== before: tasks-axi show task-g1
  state: in_flight
  links: none
== bin/fm-teardown.sh task-g1  (FM_HOME=lab, real tasks-axi 0.2.6)
●━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
●  WATCHER DOWN - SUPERVISION IS OFF
●  1 task(s) in flight, but no watcher has a fresh beacon (last beat: never, grace 300s).
●  Trust the emitted supervision protocol for this harness; do not use shell & for watcher repair.
●  This is a supervision warning only; the guarded operation WILL still run.
●  watcher supervision needs Stop-owned automatic recovery; inspect the hook registration and startup status before ending the turn.
●━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
error: task-g1's endpoint and local copy are cleaned up, but its backlog item could not be closed atomically (error: "Task pr link must be a canonical pull request URL: https://github.com/<owner>/<repo>/pull/<n> (GitHub) or https://<host>/<owner>/<repo>/pulls/<n> (Forgejo)"); the pending close is recorded and the next session start retries it
teardown rc=1
== after: tasks-axi show task-g1 --full
task:
  id: task-g1
  title: gerrit landing
  state: in_flight
  blocked: no
  blocked_by: none
  held: no
  hold_reason: "-"
  hold_kind: "-"
  hold_until: "-"
  kind: ship
  repo: "-"
  priority: "-"
  created: 2026-09-30
  closed: "-"
  deps: none
  links: none
  body: ""
== pending close record: /tmp/fm-lab.h3P7eK/state/task-g1.backlog-close
LAB=/tmp/fm-lab.h3P7eK
Evidence: Live teardown of a GitHub landing: still closes with a pr link

Source: Live teardown of a GitHub landing: still closes with a pr link

== before: tasks-axi show task-h1
  state: in_flight
  links: none
== bin/fm-teardown.sh task-h1  (FM_HOME=lab, real tasks-axi 0.2.6)
fm-gate-refuse: gate agent lifecycle permitted only against lab home /tmp/fm-lab.t5jIX0
●━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
●  WATCHER DOWN - SUPERVISION IS OFF
●  1 task(s) in flight, but no watcher has a fresh beacon (last beat: never, grace 300s).
●  Trust the emitted supervision protocol for this harness; do not use shell & for watcher repair.
●  This is a supervision warning only; the guarded operation WILL still run.
●  watcher supervision needs Stop-owned automatic recovery; inspect the hook registration and startup status before ending the turn.
●━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
/tmp/fm-lab.t5jIX0/proj: skipped: no origin remote
teardown task-h1 complete (window firstmate:fm-task-h1, worktree /tmp/fm-lab.t5jIX0/wt)
Backlog: task-h1 is closed in /tmp/fm-lab.t5jIX0/data/backlog.md. Run bin/fm-tasks-axi.sh ready for dependency-cleared candidates, check date gates, and dispatch only work whose blockers are gone and date is due.
teardown rc=0
== after: tasks-axi show task-h1 --full
task:
  id: task-h1
  title: "gerrit landing https://github.com/example/repo/pull/7"
  state: done
  blocked: no
  blocked_by: none
  held: no
  hold_reason: "-"
  hold_kind: "-"
  hold_until: "-"
  kind: ship
  repo: "-"
  priority: "-"
  created: "-"
  closed: 2026-09-30
  deps: none
  links: "pr:https://github.com/example/repo/pull/7"
  body: ""
== pending close record: absent
LAB=/tmp/fm-lab.t5jIX0
Evidence: Session-start replay of a stuck Gerrit close record: base fails, fix succeeds

Source: Session-start replay of a stuck Gerrit close record: base fails, fix succeeds

== stuck record left by base teardown:
id=task-g1
data=/tmp/fm-lab.h3P7eK/data
spawn_gen=live-task-g1
cleanup_incomplete=0
arg=--pr
arg=https://gerrit.example.com/c/project/+/12345
== replay with BASE code (bin/fm-bootstrap.sh from 65c75b0):
BACKLOG_RECONCILE: task-g1: recorded backlog close could not be replayed: error: "Task pr link must be a canonical pull request URL: https://github.com/<owner>/<repo>/pull/<n> (GitHub) or https://<host>/<owner>/<repo>/pulls/<n> (Forgejo)"
state:   state: in_flight ; record: /tmp/fm-lab.h3P7eK/state/task-g1.backlog-close
== replay with FIXED code (bin/fm-bootstrap.sh from this change):
BOOTSTRAP_INFO: closed the backlog item for task-g1 that an interrupted cleanup left open
== after replay: tasks-axi show task-g1 --full
  state: done
  closed: 2026-09-30
  links: none
  body: "Gerrit change https://gerrit.example.com/c/project/+/12345"
record: absent
Evidence: Driver script for the live teardown runs

Source: Driver script for the live teardown runs

#!/usr/bin/env bash
# Live drive: real bin/fm-teardown.sh + real tasks-axi 0.2.6 in a disposable lab home.
set -u
W=${FM_W:-/home/jthien/.no-mistakes/worktrees/153164a827ab/01M3SFAGMMDWD5ETC4XNXZT44N}
PRURL=$1; ID=${2:-task-g1}
LAB=$(mktemp -d "${TMPDIR:-/tmp}/fm-lab.XXXXXX"); "$W/bin/fm-lab-home.sh" create "$LAB" >/dev/null
mkdir -p "$LAB/tmux" "$LAB/fakebin"
# treehouse would return the worktree to the real pool; stub it (only cleanup plumbing).
printf '#!/usr/bin/env bash\nexit 0\n' > "$LAB/fakebin/treehouse"; chmod +x "$LAB/fakebin/treehouse"
git init -q -b main "$LAB/proj"; git -C "$LAB/proj" -c user.email=t@t -c user.name=t commit -q --allow-empty -m init
git -C "$LAB/proj" worktree add -q -b "fm/$ID" "$LAB/wt"
printf '%s\n' '# Backlog' '' '## In flight' '' '## Queued' '' '## Done' > "$LAB/data/backlog.md"
tasks-axi add "$ID" "gerrit landing" --kind ship --file "$LAB/data/backlog.md" >/dev/null
tasks-axi start "$ID" --file "$LAB/data/backlog.md" >/dev/null
cat > "$LAB/state/$ID.meta" <<M
window=firstmate:fm-$ID
endpoint_task_id=$ID
worktree=$LAB/wt
project=$LAB/proj
kind=ship
mode=no-mistakes
spawn_gen=live-$ID
pr=$PRURL
M
echo "== before: tasks-axi show $ID"; tasks-axi show "$ID" --file "$LAB/data/backlog.md" | grep -E 'state|links'
echo "== bin/fm-teardown.sh $ID  (FM_HOME=lab, real tasks-axi $(tasks-axi --version))"
cd "$W"
env -u NO_MISTAKES_GATE -u FM_GATE_REFUSE_BYPASS -u FM_ROOT_OVERRIDE -u FM_STATE_OVERRIDE -u FM_DATA_OVERRIDE -u FM_CONFIG_OVERRIDE -u FM_PROJECTS_OVERRIDE \
  TMUX_TMPDIR="$LAB/tmux" TMUX= FM_HOME="$LAB" PATH="$LAB/fakebin:$PATH" bin/fm-teardown.sh "$ID" 2>&1; echo "teardown rc=$?"
echo "== after: tasks-axi show $ID --full"; tasks-axi show "$ID" --file "$LAB/data/backlog.md" --full
echo "== pending close record: $(ls "$LAB/state/$ID.backlog-close" 2>/dev/null || echo absent)"
echo "LAB=$LAB"
Evidence: Captain-hold lifecycle test log

Source: Captain-hold lifecycle test log

ok - report-only unresolved captain call is reproduced and completion refuses before loss
ok - both body-decoding paths work without the allow_nonref default
ok - cleanup preserves every byte of a retained body's non-ASCII characters
ok - the completion gate attests captain-held inventory and transfers open status decisions
ok - answer records the captain's words, closes idempotently, and releases routed work
ok - release frees held work with the captain's words recorded and the body preserved
ok - captain holds become visible only after their hold-set timestamp is durable
ok - an interrupted answer preserves its hold age until close retry
ok - a deferred captain call leaves the live Captain's Call until its date and stays answerable
ok - an out-of-band close is recordable with the captain's word and nothing else
ok - ended visual review follows the same captain-hold completion owner
ok - resolved findings and decision-like prose do not create captain-held tasks
ok - terminal single-owner stale status decisions do not block empty inventory
ok - main-home and secondmate-home captain calls remain correctly routed
ok - a secondmate home publishes each hold occurrence and its answer on the parent channel
ok - secondmate resolutions publish before retiring durable retry triggers
ok - a bound channel's captured answers close their captain-held tasks at answer time
ok - only a bound captured source creates reconcile requests
ok - normal answers and their replays retire reconcile requests
ok - reconcile closes a moot call with evidence and keeps an active one open with a note
ok - reconcile outcomes apply durable mutations once across partial failures
ok - a channel source with no decision binding closes nothing
ok - legacy identities, metadata, bindings, and the shim keep working
ok - a board answer reaches the keyed-answer intake and wakes firstmate
ok - the chat channel feeds the same keyed-answer intake a captured review does
ok - completion and verification validate origins before constructing paths
ok - a status resolution over a still-open captain-held task is signalled, not closed
ok - a captain call with no routed work, a verified transfer, an open decision, and an answered call all stay silent
ok - cleanup leaves a captain-held work item open with its deliverable, and only an answer closes it
ok - release and scout report retention distinguish deliveries from rejected merge answers
ok - an interrupted cleanup keeps the captain call recoverable and session start retains it
ok - an answer before cleanup replay preserves the retained report
ok - an answer before cleanup replay notes the retained Gerrit change
ok - an unusable pending-close record names its reason instead of a bare refusal
ok - an unsupported relocated report does not wedge the captain's answer
ok - cleanup retains captain calls in the configured backlog
ok - cleanup keeps a captain-held Gerrit task open and records its change URL
ok - merge approval releases before zero-retention cleanup records completion
ok - the PR merge entrypoint refuses a captain-held task before merging
ok - the local merge entrypoint refuses a captain-held task before merging
ok - the PR merge entrypoint separates an unreadable authority record from an absent one
ok - the local merge entrypoint separates an unreadable authority record from an absent one
ok - merge entrypoints reject unsafe identities and absent state before locking
ok - merge entrypoints refuse a replacement incarnation after waiting for cleanup
ok - merge entrypoints own task state before forced cleanup can retire it
ok - a released merge passes the guarded entrypoint and remains recently landed
ok - cleanup refuses a ship row when its captain hold cannot be read
ok - skipped on markdown-only tasks-axi: verify against a beads-migrated hold
ok - skipped on markdown-only tasks-axi: verify against a prefix-migrated hold
ok - skipped on markdown-only tasks-axi: prefer a marker-noted row over a prefix namesake
ok - skipped on markdown-only tasks-axi: complete against a beads-migrated hold
ok - skipped on markdown-only tasks-axi: verify an unresolvable beads legacy id
ok - skipped on markdown-only tasks-axi: verify a derived pre-collapse key
ok - captain-hold mutations address the beads backend without a markdown override
ok - skipped on markdown-only tasks-axi: captain-hold create under due.required without types.custom

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

✅ **Review** - passed

✅ No issues found.

✅ **Test** - passed

✅ No issues found.

  • Live validation: ✅ go - 3 of 4 scenarios driven live against the product
Scenario Result Live Evidence
Teardown of a landed forge=gerrit task closes its backlog item as Done and keeps the Gerrit change URL on it ✅ pass live teardown-gerrit-after.txt: teardown rc=0, state: done, body: "Gerrit change https://gerrit.example.com/c/project/+/12345&#34;, pending close record absent. teardown-gerrit-base-65c75b0.txt shows the base…
Teardown of a landed GitHub PR task still closes with a --pr link ✅ pass live teardown-github-after.txt: state: done, links: "pr:https://github.com/example/repo/pull/7&#34;, body empty
A stuck close record that the old code wrote (arg=--pr <gerrit url>) replays to success at the next session start ✅ pass live replay-stuck-gerrit-record.txt: the base bootstrap prints BACKLOG_RECONCILE refusal and the item stays in_flight. The fixed bootstrap prints 'closed the backlog item for task-g1', the item is done wit…
A captain answer on a held Gerrit ship, given before the cleanup replay, closes the item with the change URL noted instead of failing ⏸️ untested no The prior payload did not establish a live result. This path was driven only by the regression test tests/fm-captain-hold-lifecycle.test.sh (which passes, using the real fm-captain-hold.sh with a task…
  • /tmp/fm-live-teardown.sh https://gerrit.example.com/c/project/+/12345 runs the real bin/fm-teardown.sh in a disposable home from bin/fm-lab-home.sh, using the real tasks-axi 0.2.6. Only treehouse is stubbed. Result: exit 0, state done, body "Gerrit change <url>", no close record left behind.
  • The same driver on a git archive 65c75b0 copy (the base) reproduces the bug: exit 1, state in_flight, tasks-axi refuses with "Task pr link must be a canonical pull request URL", and the close record stays.
  • /tmp/fm-live-teardown.sh https://github.com/example/repo/pull/7 task-h1 checks the GitHub case: state done, links pr:https://github.com/example/repo/pull/7, no note added.
  • FM_HOME=&lt;lab&gt; FM_BOOTSTRAP_NETWORK=skip bin/fm-bootstrap.sh was run against the stuck record the base teardown left. The base bootstrap fails the replay with the same refusal; the fixed bootstrap closes the item as Done with the Gerrit note and removes the record.
  • bash tests/fm-captain-hold-lifecycle.test.sh: includes test_answer_before_cleanup_replay_notes_a_retained_gerrit_change and test_teardown_retains_a_gerrit_captain_call_with_its_change_url.
  • bash tests/fm-teardown.test.sh and bash tests/fm-backlog-atomicity.test.sh: include the new Gerrit teardown and Gerrit replay regression tests.
✅ **Document** - passed

✅ No issues found.

⚠️ **Lint** - 1 warning
  • ⚠️ linter found issues (exit code 1)
✅ **Push** - passed

✅ No issues found.

Teardown's backlog_done_args hands every ship's recorded pr= URL to
fm_backlog_done as --pr, and tasks-axi refuses any --pr that is not a
canonical GitHub or Forgejo pull request. A Gerrit change URL therefore
left the item In flight after cleanup, and the pending backlog-close
record replayed into the same refusal at every session start.

fm_backlog_done now rewrites a --pr whose value fm_pr_url_parse reads
as a Gerrit change into --note "Gerrit change <url>". The mapping sits
at the tasks-axi call rather than in the pending-close record, so
records already written with --pr replay to a close unchanged. The
captain-held retain path records the URL in its deliverable line and
skips the update --pr it cannot make.
@greptile-apps

greptile-apps Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

[Medium risk] Changes how Gerrit change URLs are recorded in task closures.

The PR appears safe to merge; no outstanding findings or new issues in its changes were identified.

Reviews (2) · Last reviewed commit: "Merge branch 'main' into fm/fm-gerrit-ba..."

@slnkjthien slnkjthien changed the title fix(bin): record Gerrit change URLs as close notes instead of --pr fix(bin): close Gerrit-landed backlog items with the change URL as a note Sep 30, 2026
@kunchenguid
kunchenguid merged commit aedb7bb into kunchenguid:main Oct 1, 2026
21 of 22 checks passed
@kunchenguid

Copy link
Copy Markdown
Owner

Speaking as Kun's firstmate: this is merged. Thank you @slnkjthien — really appreciate you taking the time on this.

VISION.md per-rule

  • One captain, one interface: aligns — closes a stuck In-flight backlog item after Gerrit land; no new captain-facing surface.
  • Authority is explicit and never inferred: aligns — no new autonomy; only how tasks-axi done records a Gerrit change URL.
  • Scripts own the mechanics, agents own the judgment: aligns — fm_backlog_done / fm_backlog_pr_is_gerrit_change rewrite --pr → --note at the script boundary.
  • A restart is a non-event: aligns — pending state/<id>.backlog-close records with Gerrit --pr now replay to Done.
  • Delegation with a spine: aligns — ship cleanup still closes the contract; GitHub --pr unchanged.
  • The fleet outlives any vendor: aligns — uses existing fm_pr_url_parse Gerrit provider; no vendor lock-in.
  • Scope: aligns — forge=gerrit backlog close path only; leaves GitHub Enterprise (ghe.com / GHES) PR URLs are rejected: no PR registration, merge polling, or backlog PR link #5936 (GHE) open.

contract-class: restore — unconfigured GitHub teardown unchanged; forge=gerrit landing was already supposed to close the backlog item and was broken by tasks-axi refusing Gerrit URLs as --pr (post-#5427 path). Tip vs main: rewrite at fm_backlog_done / retain / captain-hold answer; tests cover teardown, replay, retain.

Merged squash as aedb7bbf3b038672cef8b700df2b65ff4491dbfd (head 4da669966450508104cb4d179416f4cbc4aa14ab). Attestation MATCH; NM SUCCESS; CI green; MERGEABLE/CLEAN. Closes #6138.

babbarc pushed a commit to babbarc/firstmate that referenced this pull request Oct 2, 2026
Conflict in bin/fm-backlog-transition-lib.sh: upstream's Gerrit close-note rewrite (kunchenguid#6140) and the fleet's Gitea close-note rewrite do the same job, so they are unified in fm_backlog_pr_link_note, which records a Gerrit change as 'Gerrit change <url>' and a Gitea/Forgejo pull request as 'PR <url>' on direct close, retained close, and captain-hold answer. Upstream's eager fm-pr-lib.sh source supersedes the fleet's lazy fm_backlog_pr_lib_helpers loader.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cleanup of a landed Gerrit task leaves its backlog item In flight: tasks-axi rejects the Gerrit change URL as --pr

2 participants