Skip to content

fix(signals): buildRegistrationReadiness can return ready:false with an empty blockers array #5946

Description

@JSONbored

Context

buildRegistrationReadiness in src/signals/registration-readiness.ts computes a RegistrationReadinessReport with separate blockers, warnings, and ready fields for a repo owner evaluating registration:

const configNeedsAttention = configQuality.level === "needs_attention";   // line 151
...
const blockers = [                                                        // lines 177-181
  ...(!isRegistered ? ["Repository is not registered in the latest LoopOver registry snapshot."] : []),
  ...(configFragile ? ["Repository config quality is fragile."] : []),
  ...(intakeBlocked ? ["Contributor intake health is blocked."] : []),
];
...
const warnings = [                                                        // lines 202-209
  ...(configNeedsAttention ? ["Repository config quality needs attention before registration promotion."] : []),
  ...
];
const ready = blockers.length === 0 && !configFragile && !configNeedsAttention;  // line 212

ready factors in configNeedsAttention (a third condition beyond blockers.length === 0), but blockers itself never includes a configNeedsAttention entry — only warnings does. So when configQuality.level === "needs_attention" and every other input (isRegistered, configFragile, intakeBlocked) is healthy, RegistrationReadinessReport.ready is false while RegistrationReadinessReport.blockers is [] — an empty list, which contradicts the field's implied contract as "the reasons registration isn't ready" (a caller can't render "why isn't this ready?" from blockers alone in this scenario; they'd have to separately cross-reference warnings and re-derive that one of them is actually gating ready).

test/unit/registration-readiness.test.ts (~lines 199-213, "warns about config attention and strained intake") already builds exactly this scenario and asserts report.ready === false and report.warnings contents, but never asserts anything about report.blockers — so this empty-blockers-while-not-ready gap is untested and unnoticed.

Requirements

  • Add a configNeedsAttention-derived entry to the blockers array (not just warnings), so blockers.length === 0 is equivalent to ready === true (modulo the same conditions ready already checks) — i.e. ready should be derivable as blockers.length === 0 without a separate !configNeedsAttention/!configFragile re-check, OR (alternative acceptable approach) keep configNeedsAttention as warning-only but change ready's definition to only depend on blockers.length === 0 — pick whichever resolves the inconsistency; the maintainer-facing contract is that blockers must fully explain any ready === false, whichever field is the source of truth.
  • Given configFragile is already both a blocker (line 179) and implicitly part of ready's calculation, prefer the first approach (add configNeedsAttention to blockers, matching how configFragile is already handled) for internal consistency between the two "needs attention" tiers of the same configQuality.level field, rather than removing configFragile's existing blocker treatment.
  • If configNeedsAttention becomes a blocker, decide whether to keep or remove its existing warnings entry (avoid the same fact being flagged as both, unless the codebase has a clear existing precedent for a condition appearing in both — check configFragile isn't also duplicated in warnings today before deciding, and follow that same precedent for consistency).
  • Do not change directPrReadiness, issueDiscoveryReadiness, or any other field's logic — this fix is scoped strictly to blockers/ready consistency for the configNeedsAttention condition.

Deliverables

  • blockers.length === 0 and ready === true are consistent — a repo with configQuality.level === "needs_attention" and no other blocking condition either has a non-empty blockers array explaining why, or ready no longer depends on configNeedsAttention independently of blockers.
  • A regression test in test/unit/registration-readiness.test.ts explicitly asserting report.blockers contents (not just report.ready/report.warnings) for the "config needs attention, everything else healthy" scenario, closing the gap in the existing test at ~line 199-213.
  • Existing tests for configFragile/intakeBlocked/!isRegistered blocker scenarios remain passing unmodified.

Test Coverage Requirements

Aim for 99%+ Codecov patch coverage (100% including the new branch/invariant) on the touched lines in src/signals/registration-readiness.ts. This is a fix for a real contract inconsistency between two fields of the same report, so the blockers-assertion regression test is required, not just incidental line coverage.

Expected Outcome

RegistrationReadinessReport.blockers fully explains every case where ready === false, so a caller rendering "why can't I register" can rely on blockers alone instead of needing to separately reconcile warnings against ready.

Links & Resources

  • src/signals/registration-readiness.ts (buildRegistrationReadiness, configNeedsAttention at line 151, blockers at lines 177-181, warnings at lines 202-209, ready at line 212)
  • test/unit/registration-readiness.test.ts (existing "warns about config attention and strained intake" test, ~lines 199-213 — the test to extend)

Metadata

Metadata

Assignees

No one assigned

    Labels

    gittensor:bugGittensor-scored bug fix — scores a 0.05x multiplier.help wantedExtra attention is needed

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions