myxce/.wolf/bugs/bug-1566.md
Rongsong Shen d26ff8870d
feat(buglog): one Markdown record per bug, checked against a record standard
The buglog was one 27K-line JSON file whose fields covered only symptom,
root cause and fix, as free text: 2% of entries named the code version a
bug was found on, 12% the build profile, 36% a way to reproduce, and 58% of
the file was OpenWolf hook auto-detections ("Missing guard clause",
"Function not marked async" on .md files).

- .claude/skills/buglog/bug-record.md: the record standard. Eight
  sections (Summary as the title, Description, Environment, Reproduction;
  Root cause, Fix, Verification, References once fixed), each with the
  content it must contain -- e.g. Environment needs the OS, the libc the
  failing binary loads (from its ELF interpreter: glibc 2.42 in the nix
  shell vs 2.40 on the host), toolchain, build profile and commit.
- .wolf/bugs/<id>.md: 500 records migrated from buglog.json; every field
  verified to round-trip. They carry legacy: true and an explicit "not
  recorded" where the old log had no such field; component derived from
  file paths, severity from keywords (else unknown), fix_commits from
  hashes in status_note/fix that git resolves (91 of 463 fixed).
- .wolf/buglog-archive.json: the 710 hook auto-detections, verbatim.
- .wolf/buglog.json is now an index generated from the records, keeping
  the fields OpenWolf's hooks and `openwolf bug search` read.
- scripts/buglog.py rewritten: new (template + Environment collected from
  the machine and --binary), check, status (refuses a status the record
  doesn't support; fixed needs Root cause, Fix, Verification and
  --commit hashes git resolves), note, recur, set, show, list, triage,
  env, index. 29 unittest cases in scripts/tests/test_buglog.py.
- scripts/git-hooks/pre-commit runs `check --staged`: incomplete staged
  records, a legacy record hand-changed to fixed without the fix-time
  sections, a new record claiming legacy: true, or a stale index refuse
  the commit.
- scripts/gitea-sync.py reads the records: issue body = the record's
  sections plus linked fix commits (origin remote, GITEA_COMMIT_REPO to
  override), and a body hash so an issue's text is refreshed when the
  record changes.
- bug-1866 rewritten to the full standard as the worked example.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 03:40:11 +00:00

3.4 KiB

id status status_updated status_note component severity timestamp last_seen occurrences files tags related legacy
bug-1566 fixed 2026-09-24 xceadmin unknown 2026-08-17T08:30:00.000Z 2026-09-19T09:00:00Z 1
src/xceadmin/src/xceadmin/cli.py
src/tools/deploy-ha.sh
xceadmin
cli
deploy-ha
config
default-port
envvar
true

bug-1566: User-reported: ./scripts/xceadmin scheduler record status (from a /xce-deploy-ha deployment)…

Description

User-reported: ./scripts/xceadmin scheduler record status (from a /xce-deploy-ha deployment) failed with 'Error: cannot connect to localhost:9991: [Errno 111] Connection refused' -- the deployment's actual --peers were localhost:9901/9902/9903, not 9991.

Environment

Not recorded (migrated from buglog.json).

Reproduction

Not recorded (migrated from buglog.json).

Root cause

xceadmin's --controller option (config push, and all 3 scheduler record start/stop/status subcommands) defaulted unconditionally to a hardcoded module constant _DEFAULT_CONTROLLER = 'localhost:9991' with no way to override it except typing --controller on every single invocation. /xce-deploy-ha's generated scripts/xceadmin wrapper (added earlier this session) was a bare passthrough (exec python3 -m xceadmin.cli "$@") that never told xceadmin what the actual deployed cluster's real ports were -- so any xceadmin command that didn't explicitly pass --controller silently tried the generic, deployment-agnostic default instead of this specific deployment's real peers, which have nothing to do with 9991 unless the deploy happened to use that exact port by coincidence.

Fix

FIXED (TDD RED->GREEN). Added envvar="XCEADMIN_CONTROLLER" to all 4 --controller click.option() decorators in cli.py (naming matches the existing XCEADMIN_SCHEMA_PATH convention in xcecommon/schema.py) -- click's built-in option-resolution precedence is CLI flag > envvar > default, so an explicit --controller still always wins. Added test_controller_option_falls_back_to_xceadmin_controller_env_var (RED pre-fix: asserted the env var value reaches the command, failed with the hardcoded default instead) and test_controller_flag_overrides_xceadmin_controller_env_var (regression lock for the override guarantee) to test_cli.py. deploy-ha.sh's generated scripts/xceadmin wrapper now exports XCEADMIN_CONTROLLER="${PEER_ARRAY[0]}" (this deployment's own first --peers candidate) before exec'ing xceadmin. GREEN: full xceadmin test suite (261 tests via direct pytest, 258 passed + 3 skipped via the meson-driven build) all pass, no regressions. LIVE VALIDATION: rebuilt via /xce-build xceadmin --incremental (bug-1565's new flag, keeping the already-built controller/worker/scheduler binaries), redeployed with --peers localhost:9901,9902,9903 (matching the user's report exactly), started the cluster + scheduler, ran the user's EXACT command (scripts/xceadmin scheduler record status) in a completely stripped environment (env -i, no nix, no network) with NO --controller flag: correctly reached localhost:9901 (confirmed by the error changing from a raw connection-refused on the wrong port to a real application-level 'scheduler not connected' before the scheduler was started, then a clean 'recording: no' / exit 0 once it was) instead of failing against the wrong hardcoded port.

Verification

Not recorded (migrated from buglog.json).

References

Not recorded (migrated from buglog.json).