docs(wolf): cerebrum learnings (bug-1923 snapshot resvals, build dir) and memory log
Also carries earlier uncommitted cerebrum entries (gitea milestones filter, standalone ASAN sim leaks, bug-1883 ctx vectors, gofmt vendor rule) and the hook-maintained memory.md log. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7d3c71fc34
commit
383e2a90e4
2 changed files with 284 additions and 245 deletions
|
|
@ -154,7 +154,15 @@
|
|||
- **(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.
|
||||
- **(2026-09-27, bug-1866) Worker (and most) meson tests run with `ASAN_OPTIONS=detect_leaks=0`, so a leak regression test can't rely on LeakSanitizer.** Compare `__sanitizer_get_current_allocated_bytes()` before/after the alloc/free round trip instead (after one warm-up round trip to settle lazy allocations), guarded by `#ifdef __SANITIZE_ADDRESS__` with a `TEST_IGNORE_MESSAGE` fallback. The nix GCC toolchain does NOT ship `<sanitizer/allocator_interface.h>` — declare `size_t __sanitizer_get_current_allocated_bytes(void);` yourself. A byte-exact delta also sizes the leak: bug-1866's 58 B showed five leaked strings, not the one LSan had reported.
|
||||
|
||||
- **(2026-09-29, gitea-sync) Gitea's issue list API silently ignores `milestone=<id>` and returns the newest issues repo-wide; only `milestones=<id>` filters.** `scripts/gitea-sync.py` used the singular form, so spec phase-state updates only ever saw page 1 (fixed 196eb90b; the first corrected run closed 61 stale phase issues). Each Gitea write takes ~1 min from this host, so a sync with more than a handful of writes exceeds a 10-min foreground timeout: run `python3 -u scripts/gitea-sync.py ...` with run_in_background (unbuffered, or a killed run loses all output). A killed run can leave Gitea items whose numbers never reached spec.json/record front matter -- check Gitea before re-running (spec phase issues are now adopted by title).
|
||||
- **(2026-09-29) Standalone ASAN `xce_scheduler --sim` exits 1 from exit-time LeakSanitizer reports (snapshot decode), not from a replay failure** -- run live `--sim-verify` replays with `ASAN_OPTIONS=detect_leaks=0` (as run-ha-soak.sh's replay gate does) and count `MISMATCH` lines. The HA soak (`run-ha-soak.sh`) must run inside `nix develop ./src` (deploy needs openssl) and needs `XCE_HA_BIN`/`XCE_HA_XT` pointing at a build dir that has controller+harness+worker+scheduler.
|
||||
- **(2026-09-29, bug-1883) Scheduler ctx vectors filled by prepare hooks are append-only (`xvec_idval_store` never dedups), so any pass that recomputes a want must reset that vector first.** A COMPOUND/ALTER job's primaries share one ctx; the job-level prepare pass reset only `.shared`, leaving the previous primary's per-host want in `.host`. Test time-sensitive replay fields with an epoch-scale timestamp plus a sub-second part: a fixture at `begin_round = 2000` ns cannot tell a correct `from` from 0 or from sub-second drift.
|
||||
|
||||
- **(2026-10-08, scheduler-sim-decision-trace 1.1, bug-1923) Shared (cluster-wide) resource values put in a sim recording's SnapshotEntry never reach `xce_scheduler --sim`.** `snapshot_load.c` skips resvals whose host decodes as `""` (not NULL), and `snapshot.c` iterates `sharedInst.count` (filled-slot count, not max index). Until fixed, test fixtures that need a shared value (e.g. a license pool) must send it as a RESVALS_FULL replay event.
|
||||
- **(2026-10-08) `xce-build.sh`'s default ASAN build dir is `src/xce.build` relative to the repo root** (the script runs from `src/`); raw meson commands from the repo root need `nix develop ./src --command meson test -C src/xce.build ...`.
|
||||
|
||||
## Do-Not-Repeat
|
||||
- **(2026-10-02) When gofmt-ing the Go frontend, never pass `gofmt -l apiserver xcecli` output straight to `gofmt -w`** -- it includes `apiserver/vendor/` and `xcecli/vendor/` (and the swag-generated `apiserver/docs/docs.go`), so a "format the 29 drifted files" pass rewrote 501 vendored files. Filter the list first (`grep -v "/vendor/\|go-cache\|docs/docs.go"`), check `git diff --stat` before committing, and restore only the vendor paths you touched (`git restore -- src/frontend/*/vendor`) if it happens.
|
||||
- **(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>`.
|
||||
- **A TDD-implementer SUBAGENT (spawned by a kiro-impl coordinator) has NO external wakeup mechanism — arming a `Monitor` tool call or a `Bash run_in_background` call and then ending the turn to "wait for a notification" just stops the subagent forever; the coordinator has to manually resume it.** (2026-08-26, xce-test-rc-file task 1.2, recurred across multiple tasks in this same spec before being called out explicitly.) Only the top-level session genuinely receives async task-notification events between turns; a subagent's turn ending IS the end of its execution for that dispatch. When a validation command (e.g. `controller_unit_test`) risks exceeding the default 120-300s Bash timeout, pass an explicit large `timeout` (e.g. 300000-600000ms) to a PLAIN FOREGROUND `Bash` call and let the tool call itself block until real output returns — never `run_in_background`, never `Monitor`, never end a turn on an unfinished command in this role. If a command is auto-moved to background because the timeout already elapsed, immediately re-run it in the foreground with a longer timeout rather than trying to "wait" for the backgrounded one.
|
||||
- **When translating a `fp_ok`-tracked, per-step-gated failure-detection pattern (like `xce-build.sh`'s dirty-fingerprint computation) into a Make `$(shell sh -c '...')` one-liner, do NOT collapse two commands into `{ cmd1; cmd2; } >"$$fp_tmp"` and gate the whole group with one `if`** — a POSIX sequential group's exit status reflects only its LAST command, so `cmd1`'s failure is silently discarded whenever `cmd2` still succeeds (2026-08-21, bug-1612: `git diff HEAD` failing was swallowed because the trailing `git ls-files | sort | xargs cat` pipe still exited 0, producing a fabricated fingerprint instead of degrading to empty). Give each step its own explicit `if ! step; then fp_ok=0; fi` (or `&&`-chain), exactly mirroring the reference script's discipline, even inside a cramped one-liner. Caught by adversarial code review with a targeted failure-injection test (wrapper `git` on `PATH` that fails only the targeted subcommand) — that test pattern is the reusable way to verify this class of fix.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue