Recognize ULID checkpoint IDs alongside legacy hex · Entire

Recognize ULID checkpoint IDs alongside legacy hex

4ec2c8d→main·

Soph·2w ago·2 files·+214 added/-9 removed

The "understanding" layer for ULID checkpoint IDs: the id package now accepts, validates, and shards both the legacy 12-char lowercase hex format and 26-char Crockford base32 ULIDs. Purely additive — hex behavior is unchanged, and generation still emits hex (emitting ULIDs is a separate, store-coupled change).

Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

Sessions

ab5934c248d2View transcript

Changes

2

// EmptyCheckpointID represents an unset or invalid checkpoint ID.
const EmptyCheckpointID CheckpointID = ""

// Pattern is the regex pattern for a valid checkpoint ID: exactly 12 lowercase hex characters.
const Pattern = `[0-9a-f]{12}`

// ULIDPattern is the regex pattern for a ULID checkpoint ID: exactly 26 Crockford
// base32 characters (digits plus uppercase A-Z excluding I, L, O, U). Future
// checkpoint IDs are expected to be ULIDs so they sort lexicographically by
// creation time.
const ULIDPattern = `[0-9ABCDEFGHJKMNPQRSTVWXYZ]{26}`

// CheckpointPattern matches a checkpoint ID in free text in either format
// (legacy 12-hex or ULID). Use this — not Pattern — when scanning text such as
// the Entire-Checkpoint commit trailer for a checkpoint ID.
const CheckpointPattern = `(?:` + Pattern + `|` + ULIDPattern + `)`

// ShortIDLength is the standard length for truncating IDs for display purposes.
const ShortIDLength = 12

// checkpointIDRegex validates the format: exactly 12 lowercase hex characters.
var checkpointIDRegex = regexp.MustCompile(`^` + Pattern + `$`)

// ulidRegex validates the ULID format: exactly 26 Crockford base32 characters.
var ulidRegex = regexp.MustCompile(`^` + ULIDPattern + `$`)

// Kind classifies a checkpoint ID by its storage format. The two valid kinds
// shard differently when stored as a git ref (see ShardFor).
type Kind int

const (
    // KindUnknown is a string matching neither the legacy hex nor the ULID format.
    KindUnknown Kind = iota
    // KindLegacy is a 12-character lowercase hex ID (the format Generate emits).
    KindLegacy
    // KindULID is a 26-character Crockford base32 ULID.
    KindULID
)

// KindOf classifies a checkpoint ID string.
func KindOf(s string) Kind {
    switch {
    case checkpointIDRegex.MatchString(s):
        return KindLegacy
    case ulidRegex.MatchString(s):
        return KindULID
    default:
        return KindUnknown
    }
}

// ShardFor returns the two-character shard for storing this ID under a
// per-checkpoint git ref (refs/entire/checkpoints/<shard>/<id>).
func (id CheckpointID) ShardFor() string {
    s := string(id)
    if len(s) < 2 {
        return s
    }
    if id.Kind() == KindULID {
        return s[len(s)-2:]
    }
    return s[:2]
}

// NewCheckpointID creates a CheckpointID from a string, validating its format.
func NewCheckpointID(s string) (CheckpointID, error) {
    if err := Validate(s); err != nil {
        return EmptyCheckpointID, err
    }
}

// Generate creates a new random 12-character hex checkpoint ID.
func Generate() (CheckpointID, error) {
    bytes := make([]byte, 6) // 6 bytes = 12 hex chars
    if _, err := rand.Read(bytes); err != nil {
    }
    return CheckpointID(hex.EncodeToString(bytes)), nil
}

// Validate checks if a string is a valid checkpoint ID format.
func Validate(s string) error {
    if !checkpointIDRegex.MatchString(s) {
        return fmt.Errorf("invalid checkpoint ID %q: must be 12 lowercase hex characters", s)
    }
    return nil
}