--- id: "bug-1745" status: "fixed" status_updated: "2026-09-24" status_note: "" component: "unknown" severity: "unknown" timestamp: "2026-09-01T00:20:00Z" last_seen: "2026-09-19T09:00:00Z" occurrences: 1 files: [".kiro/specs/worker-rejoin-resync/design.md"] tags: ["design-phase", "worker-rejoin-resync", "kiro-validate-design", "bug-1678", "bug-1631", "bug-1679", "scheduler-dispatch-commit", "not-a-runtime-bug"] related: ["bug-1678", "bug-1631", "bug-1679", "bug-1514"] legacy: true --- # bug-1745: kiro-validate-design worker-rejoin-resync (design phase, spec never implemented yet): initial pass… ## Description kiro-validate-design worker-rejoin-resync (design phase, spec never implemented yet): initial pass found 2 critical issues in design.md, self-correction during the fix pass found 2 more. None are runtime bugs (no code exists for this spec yet) -- this entry records design-document defects caught before implementation, same category as bug-1514. ## Environment _Not recorded (migrated from buglog.json)._ ## Reproduction _Not recorded (migrated from buglog.json)._ ## Root cause (1) design.md's Data Models section cited bug-1678 (WAL_JOB_DISPATCH not carrying job->allocs through replay) as a still-open, tracked gap justifying record_job_reconcile_assign_fact() not populating an allocation -- bug-1678 was actually fixed 2026-08-25, before this design.md was finalized; the citation was stale, and the design missed that persist_submit_job_dispatch_fact() (the fixed primitive) already has a tested NULL-alloc path it could directly reuse instead of inventing a new WAL fact shape. (2) design.md's dispatch-gating reuse (Requirement 5.1, XCE_WORKER_RECONCILING via dispatch_a_job_'s w->host.status != 0 check) was researched before scheduler-dispatch-commit (2026-08-24/25) added xce_classify_dispatch_fail()'s bounded-retry-then-mark_job_fail() machinery behind that exact check -- the design's own 'Revalidation Triggers' section named this exact check as a trigger but it had not actually been re-checked against current code. A RECONCILING host could be selected as a dispatch candidate by the scheduler (whose own filter only checks IS_WORKER_UNAVAIL, confirmed via grep) and then get retried-then-terminal-failed by the controller purely for being mid-reconciliation. (3) Fixing (1) surfaced bug-1631 (job.allocs never released on dispatch_a_job_'s retryable-failure paths, deliberately left unfixed because nothing in the system re-admitted an already-RUN job to the scheduler's PEND pool) -- worker-rejoin-resync's own Requirement 4.6 (unrecognized job -> return to PEND, eligible for re-dispatch) IS such a re-admission path, and design.md's record_job_reconcile_pending_fact spec did not release job->job.allocs, reactivating bug-1631's exact deferred trigger condition. (4) Fixing (3) by adding an eager job->job.allocs release exposed a self-introduced inconsistency: apply_job_update_transition() only mutates job->job.state, deferred until apply_committed_entry applies the committed fact (confirmed by reading record_job_finish_fact()'s identical deferred pattern) -- an eager allocs release paired with a deferred state change would produce a real, brief RUN-state-with-NULL-allocs window. Resolved by modeling both new job.c functions on dispatch_a_job_'s own eager-mutation-plus-explicit-persist_notify_job_updated_already_persisted pattern (bug-1679's precedent) instead, rather than record_job_finish_fact's deferred one. ## Fix All 4 corrected directly in design.md during the same validation session (not deferred to implementation): (1) Data Models' 'Documented scope decision' + Components section rewritten -- record_job_reconcile_assign_fact() now specified to call the existing, fixed persist_submit_job_dispatch_fact(alloc=NULL) directly. (2) Added a new Scheduler-side component (scheduler.c:1211's candidate filter gets one added disjunct, IS_WORKER_RECONCILING, mirroring the existing IS_WORKER_UNAVAIL check) as the primary Requirement 5.1 enforcement, with dispatch_a_job_'s existing check kept as an unmodified defensive backstop; Requirement 5.4's disconnected-worker case given its own pre-classifier branch (bypassing xce_classify_dispatch_fail entirely, not a 3rd enum value, to avoid forcing ~5 unrelated switch sites to handle a case they can't hit). (3) record_job_reconcile_pending_fact() now specified to release job->job.allocs eagerly. (4) Both new job.c functions redesigned around dispatch_a_job_'s eager-mutation + persist_notify_job_updated_already_persisted pattern, explicitly not record_job_finish_fact's deferred one, with the rationale (worker-confirmed ground truth vs. an unconfirmed local admin command) documented inline so a future editor doesn't accidentally revert to the deferred pattern. spec.json's design.approved flipped to true with a validation_note recording this trail. No code was written -- this is a design-document-only fix; implementation-time discovery may still surface further refinement, per design.md's own remaining 'must confirm at implementation time' caveats. ## Verification _Not recorded (migrated from buglog.json)._ ## References - Related: bug-1678, bug-1631, bug-1679, bug-1514