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).
- ULIDPattern + ulidRegex; Kind/KindOf + CheckpointID.Kind classify legacy/ULID/ unknown.
- ShardFor: first two chars for legacy (preserves the v1 tree layout), LAST two for ULID (leading chars are the timestamp and barely vary; the random suffix shards evenly while the ID stays lexicographically sortable).
- CheckpointPattern = (hex|ulid) for matching a checkpoint ID in free text (e.g. the Entire-Checkpoint trailer). Pattern stays 12-hex — it is reused for run IDs by investigate/provenance, which are not checkpoint IDs.
- Validate / NewCheckpointID / UnmarshalJSON accept either format (invalid only when KindOf == KindUnknown); empty-string handling unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com
Sessions
ab5934c248d2View transcript
Changes
2
- cmd/entire/cli/checkpoint/id
- Mid.go+86/-9
- Mid_test.go+128
// 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
}