Ship a New Version

palette works, but every color is a fixed value. Let's add lighten and darken, release it as 0.2.0, and see how semantic versioning carries the change to anyone who depends on you.

What the version number means

A version is MAJOR.MINOR.PATCH, and the part you bump signals what changed for your users:

  • PATCH (0.1.0 → 0.1.1) — backward-compatible bug fixes. Existing code keeps working.
  • MINOR (0.1.0 → 0.2.0) — backward-compatible new features. Existing code keeps working; there's just more it can do.
  • MAJOR (0.2.0 → 1.0.0) — breaking changes. Existing code might stop compiling.

Adding new methods is purely additive, so it's a minor bump.

Step 1 — Add the feature

Add two methods to Color. They use the standard library's saturating arithmetic so a channel clamps at 0/255 instead of wrapping:

<!-- sample: skip --> /// @name Lighten /// Returns a lighter copy of the color. /// /// Adds `amount` to every channel, clamping at 255 so a channel never wraps /// around. /// /// # Examples /// /// ``` /// Color(red: 200, green: 100, blue: 0).lighten(by: 100).toHex(); // "#ffc864" /// ``` public func lighten(by amount: UInt8) -> Color { Color( red: self.red.addSaturating(amount), green: self.green.addSaturating(amount), blue: self.blue.addSaturating(amount) ) } /// @name Darken /// Returns a darker copy of the color. /// /// Subtracts `amount` from every channel, clamping at 0. /// /// # Examples /// /// ``` /// Color(red: 200, green: 100, blue: 0).darken(by: 100).toHex(); // "#640000" /// ``` public func darken(by amount: UInt8) -> Color { Color( red: self.red.subtractSaturating(amount), green: self.green.subtractSaturating(amount), blue: self.blue.subtractSaturating(amount) ) }

This only adds to the API — every existing use of Color still compiles exactly as before. That's what makes it a minor change.

Step 2 — Bump the version

In flock.toml:

[package] name = "palette" version = "0.2.0" org = "your-name"

Step 3 — Publish it

flock publish Publishing your-name/palette@0.2.0 to https://registry.kestrel-lang.com... {"ok":true,"checksum":"sha256:…"}

0.1.0 is untouched and still available — you've published 0.2.0 alongside it. (Remember, you can't re-publish 0.1.0; versions are immutable.)

Step 4 — Dependents pick it up

Over in swatch, bump the constraint to the new version and re-resolve:

[dependencies] your-name/palette = { version = "0.2.0" } flock update

flock update re-resolves the graph and rewrites flock.lock. Now swatch can use the new methods:

<!-- sample: skip --> let brand = Color(red: 58, green: 123, blue: 213); brand.lighten(by: 40).toHex(); // "#62a3fd" brand.darken(by: 40).toHex(); // "#1253ad"

Because 0.2.0 only added to the API, swatch's existing code didn't change — it just gained access to lighten and darken.

What would be a breaking change

Some edits force a major bump because they break existing callers:

  • Renaming or removing a public item — toHex()hexString().
  • Changing a signature — making Color(hex:) return a Result instead of an Optional, or adding a required parameter.
  • Changing documented behavior callers rely on.

When you have to do one of those, bump the major version (1.0.0) so dependents opt in deliberately. Until then: patch for fixes, minor for additions.

That's the core publishing loop — build, publish, depend, version. The remaining pages are optional: Organizations & Teams for publishing with others, Publishing from CI to automate releases, and the Reference.