Shipmind Labs

A rating has to name an anchor of its own competency, or say NOT_ASSESSED out loud. Those two are the only legal values.

Interview scoring usually stores a number. 3 out of 5. The number outlives the conversation, the meaning does not. Months later nobody can rebuild what 3 meant, or whether the scale had shifted underneath it.

In sealedloop, our open-source project, the scorecard module treats a rating as a name instead of a value.

setRating resolves the competency first through requireCompetency, which throws UNKNOWN_COMPETENCY. Then it NFC-normalizes the submitted value and accepts it only if it equals NOT_ASSESSED or matches the id of an anchor belonging to that competency. A level number raises OFF_SCALE. So does an anchor borrowed from another competency, because the right word on the wrong scale is still off scale.

The rubric is pinned to the card. draftScorecard refuses a rubric with a missing rubricHash, stamps that hash onto the card, then runs loopId, candidateRef and interviewerId through requireText, which throws INVALID_SCORECARD on blank text. freezeCard seals the ratings, every evidence note, and the card itself.

The part we would argue for hardest: silence is not NOT_ASSESSED. checkSubmittable walks the rubric's competencies in declared order and throws MISSING_RATING wherever the card holds no entry. An unfilled row is a missing decision, not a neutral one, and the only way to say "we did not get to this" is to say it.

Edges cost more than middles. edgeName marks the first or last anchor as bottom or top, and a rating at an edge needs an evidence note under the same competency whose trimmed character count reaches the rubric's minimum, or EVIDENCE_REQUIRED. Middle anchors need none. A claim at an extreme carries the burden of proof, an ordinary one does not.

And unassessed is not bad. anchorPosition returns null for NOT_ASSESSED and the declared level otherwise, so an unassessed competency does not sort below the lowest anchor. The rubric builder also refuses any anchor id equal to NOT_ASSESSED, so the two vocabularies cannot collide.

This is not really about hiring. Credit decisions, compliance review, moderation, risk scoring: they all have the same hole, since a number keeps its shape while its meaning drifts. Named levels, an explicit not-assessed, and evidence at the extremes leave a record that still means something after the person who wrote it has moved on.

So it is worth knowing where your team keeps the reasoning behind a scored decision, inside the record or in a free-text field nobody reads.

Was this useful?

Building something similar?

or email hello@shipmindlabs.com