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>
7 KiB
| id | status | status_updated | status_note | component | severity | timestamp | last_seen | occurrences | files | tags | related | legacy | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| bug-1590 | fixed | 2026-09-24 | scheduler | unknown | 2026-08-19T03:40:00Z | 2026-09-19T09:00:00Z | 2 |
|
|
|
true |
bug-1590: User-reported: (sim) info worker all in the scheduler's interactive REPL shows `resource type…
Description
User-reported: (sim) info worker all in the scheduler's interactive REPL shows resource type: total=0.00 available=0.00 and resource model: total=0.00 available=0.00 -- but type/model are STRING-valued resources (e.g. OS type, hardware model name), not numeric, so 0.00 is meaningless. User also notes boolean-typed resources exist and asked to verify resource-value type-correct formatting broadly, across both REPL output and log lines, not just this one command.
Environment
Not recorded (migrated from buglog.json).
Reproduction
Not recorded (migrated from buglog.json).
Root cause
CONFIRMED via source read across the whole stack (C scheduler/controller/worker + Go apiserver/xcecli), several distinct severities under one theme -- 'resource values are not type-dispatched when formatted for display/log, several call sites assume every resource is numeric (Value_u_fvalue)':
(1) MOST SEVERE, matches the exact user report -- repl_info_worker_one() (repl_info.c:329-334): avail = (avail_v->which == Value_u_fvalue) ? avail_v->u.fvalue : 0.0; then unconditionally fprintf(..., "total=%.2f available=%.2f", ...) -- ANY resource whose wire value is Value_u_svalue (string, e.g. type/model) or Value_u_bvalue (boolean) silently renders as 0.00, indistinguishable from a genuinely-zero numeric resource. Comment at line 324-328 references bug-1568 (a DIFFERENT, already-fixed bug about comparing against the wrong enum) but bug-1568's fix never added string/bool handling -- it only made the numeric case correct.
(2) Same defect, repl_info_resource_one() (repl_info.c:436-444, info resource <name>): the total/available aggregation loop only accumulates when ->which == Value_u_fvalue (correctly guarded, no UB) -- but silently EXCLUDES string/bool resources from the sum entirely, so info resource type/info resource model would also show total=0.00 available=0.00 despite valtype=string being correctly labeled two lines below it (line 489-495) -- an internally inconsistent-looking display (correct type label, wrong/misleading value).
(3) Related, narrower gap in scheduler logging -- core_events.c's bug-1573 fix (~838-861, the 'resval applied host=... resource=... value=...' TRACE line) DOES correctly branch Value_u_svalue -> '%s' vs Value_u_fvalue -> '%f', but its own comment self-documents that Value_u_bvalue (boolean) is 'silently skipped here rather than guessed at' -- confirmed still true as of this reading: no case handles Value_u_bvalue, so a boolean resource update produces NO trace line at all (silent omission, not a wrong value, but incomplete visibility for exactly the resource kind the user flagged).
(4) Minor/lower severity, controller-side -- worker.c (~107-119) has an else branch for non-fvalue that logs which=%d (non-numeric) (informative about the presence of a non-numeric update, but never decodes/prints the actual string or boolean value); dataex.c (~86-90) has NO else branch at all -- silently skips the TRACE entirely for any non-fvalue resource, weakest visibility of the four sites but least user-facing (debug-level TRACE only).
POSITIVE finding, scoped this from being a systemic whole-stack issue: the Go apiserver's cNameValToWorkerResval() (src/frontend/apiserver/backend/convert.go:325-370) is a CORRECT, COMPLETE reference implementation -- it switches on all 7 Value_u_which wire tags (ivalue32/ivalue64/uvalue32/uvalue64/fvalue all -> NUMERIC/NumericValue, svalue -> STRING/StringValue, bvalue -> BOOLEAN/BooleanValue, matching models.ResourceDistributionInfo's already-correctly-typed fields, src/frontend/apiserver/models/resources.go:118-126), plus a default: WARN log for any unrecognized tag. src/frontend/xcecli/models/resource.go's ResourceValue.UnmarshalJSON() (client-side) also correctly handles string/bool/numeric JSON values. So the production REST API (apiserver) and xcecli CLI resource-value display path are NOT affected -- this bug is confined to the scheduler's own C-side simulation-debugging REPL (repl_info.c, the user-facing symptom) and a handful of C-side TRACE/debug log call sites in the scheduler/controller (lower severity, debug-visibility-only gaps).
Fix
Fixed. src/scheduler/src/repl_info.c: repl_info_worker_one() (info worker <name>|all) now switches on the resval's real Value_u_which wire tag -- Value_u_svalue prints resource <name>: value=<string>, Value_u_bvalue prints resource <name>: value=true|false, Value_u_fvalue keeps the existing total=%.2f available=%.2f numeric display unchanged. repl_info_resource_one() (info resource <name>) got the analogous fix one layer up: the per-worker aggregation loop now tracks the first-seen string/boolean value (in addition to the existing numeric total/available sum), and the final print branches on the resource DEFINITION's authoritative r->valtype (XCE_VAL_STRING/XCE_VAL_BOOLEAN/XCE_VAL_NUMERIC, xce/types.h) to decide which of value=<v> (with a 'reported by N worker(s)' count) vs. the numeric total/available pair to print -- total/available is a consumable-quantity concept that is only meaningful for a numeric resource, so a string/boolean resource no longer gets a fabricated total=0.00/available=0.00 pair at all. TDD: added test_info_worker_reports_string_and_boolean_resource_values and test_info_resource_reports_string_value to test_repl_breakpoints_inspection.c, both constructing a real WORKERS_PUSH event with a string- and boolean-valued resource through the actual xce_core_push_events() path (same fixture idiom the existing bug-1568 numeric-resource test already established), asserting the new value= lines appear and no total= line is ever emitted for a non-numeric resource. Verified via a full non-incremental /xce-build scheduler asan run (fresh wipe+reconfigure, not reusing any cached object): zero compiler errors, both new tests confirmed PASS in testlog.txt, full suite Ok:41/Fail:1 out of 42 -- the sole failure is the pre-existing unrelated bug-1560 (test_admin_request's symlink-escape test). core_events.c's separately-noted boolean-TRACE gap (item 3 in this entry's root_cause) and worker.c/dataex.c's non-numeric TRACE decode gaps (item 4) were NOT touched -- left as documented, lower-priority follow-ups, not part of this fix's scope.
Verification
Not recorded (migrated from buglog.json).
References
- Related: bug-1568, bug-1573