fix(gitea): push 撞到別台機器時是本機贏,但不能靜靜地贏
`pushArea` 遇到 non-fast-forward 時會 `git reset --hard origin/<branch>`、
把本機工作副本重新疊上去再推一次,然後回 `{ok:true, changed:true}`——
沒有任何衝突訊號。而 Stop hook 每一輪都在背景 push,所以兩台機器同時聊同一個
人格時,對方的 emotion.json/short-term.jsonl 會被靜默取代,誰都不知道。
「本機工作副本是這台機器的真相來源」這個設計選擇保留,但那條路徑現在要記帳:
* 算出「對方在分歧後改過、而我們正要蓋掉」的檔案交集,連同覆蓋前的遠端 sha
一起回傳 `overwrote`,並寫進 state/sync.json(留最近 10 筆)。
* `sync push` 一律往 stderr 寫一行警告(--quiet 也寫,背景 push 才有痕跡),
正常輸出與 `sync status` 都列得出「蓋掉幾個檔案、上一版是誰」。
* 背景 push 是 detached、輸出丟掉的,所以由 Stop hook 認領未回報的紀錄,
講給使用者聽一次(劇場模式也照講——那是資料被蓋掉)。
* commit 訊息也寫進「覆蓋 N 個檔案,上一版 <sha>」,被蓋掉的內容仍可用
`git -C <人格>/.sync/<區> show <sha>:<檔案>` 取回。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -45,11 +45,24 @@ if (!gt.giteaProblem() && gt.personaCode(host) && gt.pushDue(host, "files")) {
|
||||
}
|
||||
|
||||
const out = { suppressOutput: true };
|
||||
// 背景 push 撞到別台機器時是「本機覆蓋遠端」。那條路徑會把帳記在 sync.json,
|
||||
// 但它是 detached 跑的、輸出丟掉,所以由這裡認領並回報一次——劇場模式也照報(那是資料被蓋掉)。
|
||||
const overwrites = gt.pendingOverwrites(host);
|
||||
if (overwrites.length) {
|
||||
gt.markOverwritesReported(host);
|
||||
const files = [...new Set(overwrites.flatMap((o) => o.files || []))];
|
||||
const last = overwrites.at(-1);
|
||||
out.systemMessage =
|
||||
`[jsc-persona] ⚠ \`${host}\` 同步到 Gitea 時**以本機為準覆蓋了遠端** ${files.length} 個檔案` +
|
||||
`(${files.slice(0, 5).join(", ")}${files.length > 5 ? "…" : ""}),上一版是 ${String(last.previous).slice(0, 8)}。` +
|
||||
"別台機器可能正在用同一個人格;細節見 `sync status`。";
|
||||
}
|
||||
if (!theater) {
|
||||
const { total, candidates } = pl.promotionCandidates(host);
|
||||
if (candidates.length) {
|
||||
const rules = [...new Set(candidates.flatMap((c) => c.rules))].sort().join("/");
|
||||
out.systemMessage =
|
||||
`${out.systemMessage ? `${out.systemMessage}\n` : ""}` +
|
||||
`[jsc-persona] \`${host}\` 短期記憶 ${total} 筆,${candidates.length} 組已達固化條件(${rules})` +
|
||||
"→ 建議執行 /jsc-persona:persona-memory。";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user