- .wolf/anatomy*, memory.md: hook-maintained index and session log through the bug-1851..1854 work. - .kiro/specs/libxce-alloc-preason-equality/: requirements, design, research and tasks generated; none approved yet (spec.json phase tasks-generated). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
7.7 KiB
7.7 KiB
Research & Design Decisions
Summary
- Feature:
libxce-alloc-preason-equality - Discovery Scope: Extension (relocate existing comparison logic, add public API, migrate consumers)
- Key Findings:
- The type-level equality comparators in
sim_verify.coperate purely on libxce structs with zero scheduler/capnp/replay dependency — they are cleanly movable; the decision-level dispatcher and mismatch reporting are not. - The comparators are already shared across four translation units, but via white-box
#include "../src/sim_verify.c"+ direct calls tostaticfunctions (test_sim_equivalence.c,test_repl_equivalence.c,test_repl_limit_table.c). - The controller (
persist.c,resync.c,job.c) already consumesxce_job_alloc_t/xce_host_alloc_t/xce_job_preason_t/xce_alloc_twith no equality API — confirming these structs are genuinely cross-component, not scheduler-only. - One deliberate field exclusion is baked into the alloc comparators (
from/instid), which generalizes cleanly into a shared identity contract. The preason comparator's main-reason-only narrowing is not an identity property — it is a replay artifact (bug-1845) that must stay in the simulator while the sharedjob_preason_eqbecomes a full match.
- The type-level equality comparators in
Research Log
Where do the equality checks live?
- Context: locate all comparison logic in the scheduler simulator.
- Sources Consulted:
src/scheduler/src/sim_verify.c(full read);src/scheduler/src/sim_loop.c,sim_alloc.c,sim_picker.c,sim_limit.c(grep for_eq/_equal/compare). - Findings:
sim_verify.c(474 lines) is the only file with equality logic. It holds fivestaticleaf comparators plussim_decision_eq,sim_log_mismatch, and twodescribe_*helpers. No other sim file compares these structs. - Implications: the split point is exactly between the five
staticleaf functions andsim_decision_eq.
Who consumes these comparators, and how?
- Context: understand the "future sharing" concern.
- Sources Consulted: grep for
sim_verify_job_alloc_eq/sim_verify_job_preason_eq/sim_verify_alloc_eqacrosssrc/scheduler/testsuite/. - Findings: three test files call the two leaf comparators directly after white-box-including
sim_verify.c:test_sim_equivalence.c:894,902,test_repl_equivalence.c:734,742,test_repl_limit_table.c:2662,2670. Each builds its ownreplay_decision_content_eq-style helper on top of the two leaves. - Implications: moving the leaves to libxce turns a fragile include-and-call-static hack into a normal public API; these three files must migrate their call sites.
Are these structs shared beyond the scheduler?
- Context: justify libxce as the destination rather than "scheduler convenience".
- Sources Consulted: grep for the four struct names across
src/controller,src/worker,src/harness,src/lib. - Findings:
xce_job_alloc_t/xce_host_alloc_t/xce_job_preason_t/xce_alloc_tare consumed bysrc/controller/persist.c(Cap'n Proto encode/decode),src/controller/resync.c, andsrc/controller/job.c, plus the scheduler. No equality API exists anywhere. - Implications: the controller is a real future consumer of equality; the API belongs in libxce.
Where do the structs' construction/dup helpers already live?
- Context: choose the destination module.
- Sources Consulted:
src/lib/xcealloc.c(read full),src/include/xcealloc.h,src/lib/preason.c,src/include/preason.h. - Findings:
make_alloc/make_host_alloc/make_job_alloc/dup_job_alloc/make_job_accountinxcealloc.c;erase_job_preason/add_job_preason/make_pendreasoninpreason.c. No existing_eq/_equalconvention in libxce (onlyfloat_equalinutils.h); no NULL-safe string-equality helper exists. - Implications: co-location with construction is the natural home; the string helper is new and only needed by the alloc family today.
Architecture Pattern Evaluation
| Option | Description | Strengths | Risks / Limitations | Notes |
|---|---|---|---|---|
| Co-locate in existing modules | equality beside make_*/dup_*/erase_* |
matches precedent, no new module | none material | selected |
New xce_equality.{c,h} |
one module for all four | single discoverable location | new module for 4 small functions | rejected (YAGNI) |
| Leave in scheduler, expose via header | promote the statics to scheduler-external | minimal | controller can't use them; wrong ownership | rejected |
Design Decisions
(Full decisions live in design.md; the significant trade-offs are recapped here.)
Decision: job_preason_eq is a full structural match; the simulator keeps its own main-reason-only PEND check
- Context:
sim_verify_job_preason_eqcompares onlymain_reason, deliberately (bug-1845) — sim has no alloc cache, so its full detail can never match a recorded cache-hit's main-reason-only shape; requiring detail to match produced systematic false mismatches. That narrowing answers "same replay outcome", not "identical pending-reason objects". - Alternatives Considered:
- Publish full-deep
job_preason_eq+ keep astaticmain-reason-only helper insim_verify.cfor the PEND branch (selected). - Publish
job_preason_eqas main-reason-only (rejected — leaks a replay artifact into a general-purpose equality API).
- Publish full-deep
- Selected Approach:
job_preason_eq(a, b)returns non-zero iffmain_reasonmatches and both detail lists (host-based, resource-based) match in order field-for-field.sim_decision_eq's PEND branch uses a small simulator-localstaticmain-reason-only comparison instead ofjob_preason_eq. - Rationale: a public "same pending reason" predicate must be identity-honest; the replay asymmetry is a scheduler-only concern and stays where it belongs.
- Trade-offs: two PEND-comparison shapes exist (full-match in libxce, main-reason-only in sim_verify.c) — intentional, they answer different questions, and the sim-local helper is
staticand small. - Follow-up: none expected; the sim-local helper is not exported.
Decision: preserve NULL and order semantics exactly
- Context: the current leaf comparators use "identical pointer (including both NULL) → equal; exactly one NULL → not-equal", and ordered list comparison.
- Selected Approach: reproduce exactly in libxce.
- Rationale: the relocation is required to be zero-behavioral-change (Requirement 3); ordered comparison is correct because both sides come from the same deterministic construction.
Risks & Mitigations
- Risk: a consumer silently relies on the excluded fields (
from/instid, preason detail) → Mitigation: explicit doc contract on each function + revalidation triggers; no behavior change for existing consumers. - Risk: migration of the three white-box test files breaks their
replay_decision_content_eqhelpers → Mitigation: mechanical call-site rename, verified by the full scheduler suite (task 7). - Risk: duplicate-symbol collisions if a test both white-box-includes
sim_verify.cand links libxce after the statics are removed → Mitigation: the statics are deleted fromsim_verify.c(task 4) before the test files migrate (task 5), so the names resolve only against libxce.
References
src/scheduler/src/sim_verify.c— current home of the comparators (source of truth for field lists and exclusion rationale).src/include/xce/types.h— the four struct definitions.src/lib/xcealloc.c,src/lib/preason.c— destination modules and their construction/dup conventions..kiro/specs/scheduler-snapshot-job-allocation/— precedent for a scheduler-driven spec adding libxce helpers (dup_job_alloc) toxcealloc.c.