Skip to content

fix: pids が尽きて git を起こせなかった回の未 push 観測が、前に取れていた枝名を台帳から消さないようにする - #4398

Merged
takecchi merged 2 commits into
mainfrom
fix/1266-keep-branch-on-fork-failure
Oct 10, 2026
Merged

takecchi merged 2 commits into
mainfrom
fix/1266-keep-branch-on-fork-failure

Conversation

@takecchi

Copy link
Copy Markdown
Owner

Refs #1266

何が残っていたか

#1266 の「取りに行く経路」(closed / vacate / shutdown / stop / report / tool_use / 退避 ref)は main に全部入っている。ただし pids が尽きて fork が断られる器(今日 heosterra の担当が何度も当たった形。#1334 / #2626)では、取りに行った観測そのものが前に取れていた枝名を台帳から消していた。

  • computeUnpushedWork は作業ツリーを readdir で探すので、fork できなくても作業ツリーは見つかる。一方 git rev-parse などは起こせないので、branch: null で kind: 'observed' の観測になる。
  • 台帳の上書きガード(isUnpushedWorkObservationAtLeastAsNewAs)は時刻しか比べないため、この「より新しい観測」が、それより前の report / tool_use で取れていた枝名をそのまま上書きしていた。
  • 委譲が SIGABRT で落ちる直前の closed の観測がまさにこの形になる。器が消えた後に台帳から引けるのは branch=null(取れなかった) だけになる。
  • 併せて、件数の理由は fork の失敗(exit コード無し)を「git rev-list が exit null——HEAD が無効である可能性が高い」と誤って名乗っていた。

変えたこと

  • 台帳へ書く2か所(#recordUnpushedWorkObservation と case 'closed')で、新しい観測の branch: null の作業ツリーが前の観測では枝名を持っていたら、枝名を引き継ぐ。この観測で取れなかった remoteOrigin も同じく引き継ぐ。引き継いだ時刻は branchCarriedFromAt で名乗る。
    • 件数(unpushedCommitCountUnknown など)は引き継がない。この観測の「確かめられなかった」のまま残す。
    • unavailable の観測へは引き継がない。欄の形が違い、「確かめられなかった」を観測で埋めないため。
  • manager_list・CLI・Web の詳細・器の入れ替え後の nudge は、引き継いだ枝名に「◯◯時点の観測から引き継いだ」を添える。整形は describeObservedWorktreeBranch に寄せ、3か所で同じ文言にした。
  • runGit は spawn の失敗(error イベント)の errno code を返す。件数の理由は「git を起こせなかった: EAGAIN」になる。message はパスを含みうるので運ばない。
  • apps/daemon/openapi.json を pnpm --filter "@alteroid/daemon..." build で再生成した(欄が1つ増えただけ)。

なぜ null の理由(detached HEAD か失敗か)で分けないか

runner の protocol に新しい欄を足せば分けられる。ただ、引き継いだ枝名は「branchCarriedFromAt の時刻にはその枝だった」という意味で正しく、時刻を名乗るので嘘にはならない(rebase 途中の detached HEAD でも同じ)。runner と daemon の版のずれも持ち込まずに済む。

確かめたこと(ローカル。2026-10-10T02:30Z)

  • pnpm --filter @alteroid/core --filter @alteroid/cli --filter @alteroid/web typecheck は緑。CLI は依存を build した後に緑になった。
  • vitest run で manager-closed-unpushed-work / unpushed-work / unpushed-work-observation-format / manager-workspace-nudge / manager-shutdown-unpushed-work / manager-abort-unpushed-work が 6 files / 143 tests 緑。
  • 変更したファイルに prettier --check と eslint を通した。
  • 足した歯:
    • fork が断られた closed が前の枝名と origin を引き継ぎ、時刻を名乗る。
    • 続けて取れなかった回でも、引き継いだ時刻が動かない。
    • 対照として、取れたら印を残さないこと、別の作業ツリーの枝名は引き継がないことを確かめた。
    • EAGAIN を出す偽の spawn で、件数の理由が「git を起こせなかった: EAGAIN」になる。

確かめていないこと

  • 本番の器で fork が断られた回に、実際にこの形(observed で branch: null)の観測が台帳へ届いているか。根拠はコードの読みだけである。runGit は spawn の失敗を catch して exitCode: null を返し、findGitDirs は readdir だけで fork しない。
  • 退避の記録(lastRescue)の branch も、mergeRescue が新しい値で上書きするので、同じ回に null になりうる。退避 ref(pushed)は引き継がれるので取り戻す手順は残る。そのためこの PR では触っていない。

Alteroid-Issue-Done: none

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.

1 participant