chore: gitea-sync --ids, sync recent bugs (#264-#286), refresh STATUS.md

gitea-sync.py: --ids syncs named bugs regardless of dates (OR'd with
--since). Bulk triage bumped last_seen/status_updated across most of the
buglog, so --since 2026-09-01 matched ~1150 bugs while recently fixed older
bugs (bug-1798..1804, 1714, 1754, 1850, 1854) could never be reached.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Rongsong Shen 2026-09-26 07:26:45 +00:00
parent e3f5a813c6
commit ff4e2cb84e
Signed by untrusted user: rshen
GPG key ID: 80533536B0EB651C
5 changed files with 90 additions and 20 deletions

View file

@ -151,6 +151,7 @@
- **(2026-08-26, bug-1713) In this sandbox's local-loopback 3-node deploy, the FIRST-BOOT election-settling window varies wildly run to run (sometimes near-instant, sometimes ~10-12s via a term-1 election-timeout-then-PreVote-failover fallback path) — a fixed "wait for start-all.sh's health-check, then fire N requests" tight loop is NOT a reliable way to catch a transient `E_XCE_NOT_READY`/`E_XCE_NOMASTER` window: by the time start-all.sh's own 1s-granularity health-check first observes `CTRL_PRIMARY` in a log and returns, `ha_has_write_quorum()`'s `standby_endpoints` (populated synchronously inside `raft_cb_become_leader` from the raft library's own connected-voter set) is typically ALREADY satisfied, so the gate is already open. A REAL FAILOVER (kill -9 the current primary, then hammer the survivors with NO sleep, no health-check wait) reproduced the exact live symptom reliably instead — got a genuine bare `-10013` at ~t+8.6s post-kill on an unfixed client, and confirmed zero such failures surfaced across the equivalent window on the fixed client. The bug's own root-cause writeup already named this as an equally-valid trigger ("...or any time a real failover is in flight") — prefer the failover trigger over racing first-boot timing when a live repro is needed and cold-boot timing proves flaky.
- **(2026-08-26) A hand-rolled multi-connection mock TCP/TLS server in a test file needs a genuinely FINITE accept loop (`for handler in handlers:`), not `while self._handlers:` guarding a list that's never mutated — the latter is an always-true condition that leaves the server thread blocked in `accept()` indefinitely once the test's real client stops connecting, which does not fail the test but silently adds `thread.join(timeout=N)`'s FULL timeout to every such test's teardown (measured: 3 tests each added a flat 5s of pure teardown wait with zero effect on pass/fail).** Match the mock's handler-list length exactly to the number of connections the test actually expects (assert on `connection_count` for the "stops on its own budget" property instead of over-provisioning handlers "just in case") and additionally set a short `socket.settimeout()` on the listener as a safety net so a hypothetical future regression that causes MORE connections than expected still fails within one timeout window instead of silently reintroducing the same multi-second stall.
- **[2026-09-24: open/closed now lives in each entry's `status` field (`.claude/rules/buglog-status.md`), not in `tags` or `fix` text.]** **(2026-09-19, `/xce-audit-invariants scheduler` after `scheduler-sim-live-allocation`) A buglog entry's `tags` array can say `"fixed"` while its own `fix` text says `"Not yet fixed"` — a self-contradiction that survives silently unless something actually re-reads the entry, because most tooling in this project checks tags, not the narrative field.** Found on bug-1682 (and its unnoticed duplicate, bug-1492 — same defect, `plugin_end_session()` guarding on `begin_session_fn` instead of `end_session_fn`, independently filed twice 7 weeks apart because bug-1681's investigation never cross-referenced the earlier entry) via an audit subagent that read BOTH the code and the buglog text, not just the tags — it caught that `plugin.c:441` was still visibly broken despite the tags claiming otherwise. **Lesson 1**: when closing out a large feature and bulk-stamping buglog entries as fixed/superseded, verify each stamped entry's `fix` narrative actually matches the tag before writing it — a tag-only update is a claim with no evidence behind it. **Lesson 2**: before filing a new bug for a defect discovered "while fixing X," grep buglog.json for the exact symptom text first (e.g. `grep -i "begin_session_fn.*end_session_fn"`) — this exact one-line guard/call mismatch was independently re-discovered and re-filed as a "new" bug once already in this project's history.
- **(2026-09-26, bug-1754) A worker reports a job that exits NONZERO as a FAIL fact, not a FINISH: `xcecd_job_finished()` (worker/src/controller_connector.c) calls `xcecd_notify_job_fail(jobid, stage, exit_code)` whenever `exit_code != 0`, and only sends `xcecli_notify_jobfinish` for exit 0.** So `on_job_finish`/WAL_JOB_FINISH only ever sees successful jobs in production, and anything about a failed job's exit code (exit_info, JOB_FAIL hook payloads, apiserver notify) lives on the `on_job_fail` -> `record_job_fail_fact` -> WAL_JOB_FAIL path, where `job_failinfo_t.code` is the job's real exit code for MAIN-stage failures (but the post-exec script's code for POST_EXEC/Q_POST_EXEC, and a -errno for controller-internal `mark_job_fail` callers). Check both paths before assuming a job-exit fix is complete.
## Do-Not-Repeat
- **(2026-09-24) Never hand-edit or re-serialize `.wolf/buglog.json` to log a bug or change its status; use the `buglog` skill (`scripts/buglog.py add | status | note | recur | list | show | triage`).** Each entry's `status` (open / partial / investigating / fixed / cannot-reproduce / wontfix / duplicate, defined in `.claude/rules/buglog-status.md`) is the only source of truth for open/closed. Never infer it from `fix` text or `tags`; both drifted (bug-1772, bug-1682), and gitea-sync closed unfixed bugs by trusting a non-empty `fix` (bug-1855). `add` picks max id + 1. OpenWolf's hook uses entry count + 1, which collides, so its auto-detection is off (bug-1856). After a fix commit: `scripts/buglog.py status <id> fixed --note <sha>`.